1. Overview
Mango is a roughly a set of utilities and data structures that make java more convenient to use (in particular for Natural Language Processing, Text Mining, and Machine Learning). It is Apache 2.0 licensed allowing it to be used for whatever purpose. Mango is similar to Guava, Apache Commons Lang, and Apache Commons Collections. The main reasons for creating Mango and not relying on existing libraries are:
-
These libaries (especially Guava) are widely used and often cause version conflicts. They (Guava) often have breaking changes, which can cause can code to not work at all or as intended. Shading jars is a possibility, but is not optimal.
-
Better control and integration into functionality not provided by this libaries.
-
Use of Java 8’s built-in functional interfaces without the need for unused classes.
In addition, Mango provides helpful concepts, such as a generic Resources and easily distributed Mango Streams, utilities for converting from one type to another, and an easier to use wrapper around Java’s reflection capabilities. Finally, Mango has an intuitive Configuration and Application framework that makes it simple to get command line and gui applications up and running.
2. Installation
Mango requires Java 11 and is available via the maven central repository.
Core Mango:
<dependency>
<groupId>com.gengoai</groupId>
<artifactId>mango</artifactId>
<version>1.1</version>
</dependency>
Special Mango Annotations like Preload:
<dependency>
<groupId>com.gengoai</groupId>
<artifactId>mango-annoations</artifactId>
<version>1.1</version>
</dependency>
Swing Applications and Helpers:
<dependency>
<groupId>com.gengoai</groupId>
<artifactId>mango-swing-ui</artifactId>
<version>1.1</version>
</dependency>
SQL framework:
<dependency>
<groupId>com.gengoai</groupId>
<artifactId>mango-sql</artifactId>
<version>1.1</version>
</dependency>
2.1. Dependencies
2.1.1. Runtime
| Library | License | URL |
|---|---|---|
sqlite-jdbc (mango-sql) |
Apache 2 |
|
Jackson |
Apache 2 |
|
MapDB (1.0.9) |
Apache 2 |
|
juniversalchardet |
MPL |
|
Apache Commons-Compress |
Apache 2 |
|
flatlaf (mang-swing-ui) |
Apache 2 |
2.1.2. Compile
| Library | License | URL |
|---|---|---|
metainf-services |
MIT |
|
lombok |
MIT |
2.1.3. Optional
| Library | License | URL |
|---|---|---|
Apache Spark |
Apache 2 |
3. Collections
Mango provides a variety of useful custom collections and convenience methods for working with collections. Some of the custom collections will be familiar to those who have used Guava or Apache Common Collections. Mango provides custom implementations as to not rely on these 3rd party libraries that are often used and result in version conflicts.
3.1. Utility Classes
Mango provides utility classes for accessing and manipulating the base Java collections. The following table lists the utility class for the given Java type.
| Java Type | Mango Utility Class |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The utility classes provide methods for creating new instances and manipulating existing instances. Methods used to create an instance of a given type are defined as follows:
asTYPE(...) (1)
TYPEOf(...) (2)
| 1 | Converts an existing Java util type into the defined TYPE of collection, e.g. asArrayList(Iterable<?>) will convert an Iterable into an ArrayList . |
| 2 | Creates a new instance of the defined TYPE , e.g. hashSetOf(T…) will create a HashSet containing the given items. |
Methods for manipulating collections varying based on type. We refer the reader to the JavaDoc.
3.2. Counters
A counter is mapping from an Object
to a Double
where the double value represents a count.
A double value is used in case the value represents a normalized count.
Mango provides the Counters
utility class for constructing new Counters.
Currently, Mango provides a HashMapCounter
and a ConcurrentHashMapCounter
implementation.
In addition to the standard Counters, Mango provides a MultiCounter
which maps a tuple of objects to a value.
Mango provides the MutliCounters
utility class for constructing new MultiCounters.
Currently, Mango provides a HashMapMultiCounter
and a ConcurrentHashMapMultiCounter
implementation.
Both Counters and MultiCounters provide numerous methods to manipulate and query the counts of the objects. These methods include finding the top or bottom N items, filtering by key or value, and determining the minimum and maximum values and their associated objects.
3.3. Multimaps and Tables
A Multimap
maps keys to multiple values.
They act as a Map<K, Collection<V>
where individual implementations specify the type of collection, e.g. List, Set, etc.
Mango currently provides Multimap implementations wrapping the following collection types:
-
ArrayList
-
LinkedList
-
Set
-
LinkedHashSet
-
TreeSet
In all cases the backing map used is a HashMap
.
Multimaps provide views over the keys and values the same as a Java Map. These views update the underlying Multimap when changed (e.g. items are deleted). Please see the JavaDoc for the full list of methods available on Multimaps.
A table is a two-dimensional structure that associates a value with two keys (i.e. a row and column key).
A table maybe sparse, meaning not all cells contain values.
Methods on a table that work with rows and columns return Map views that when updated will be reflected in table.
Currently, Mango provides a single table implementation, HashBasedTable
, which wraps Java’s HashMap.
3.4. Trees
Mango provides two tree-based datastructures.
The first is an IntervalTree
which facilitates fast lookup of ranges including overlapping ranges.
Interval Trees are a Set-like object which take subclasses of Span
as their values.
A Span
defines a start and end range.
Interval tress provide similar methods to those on a NaviagableSet
with an additional method overlapping(Span)
which provides fast lookup of all Spans in the tree that overlap with the given span.
Mango also provides a basic Trie
implementation that facilitates fast prefix lookups in strings.
The Trie implements the Map interface where the key is a String and the value can be defined per use.
The Trie class provides some useful methods for suggesting the most similar strings given a maximum edit distance and finding all matches of the keys in the Trie in a given String.
3.5. Graphs
Mango provides a basic graph data structure which is currently has one implementation backed by a Table
.
Mango graphs can be defined as being directed or undirected by defining the EdgeFactory
used by the graph.
A number of graph algorithms and traversal strategies are implemented including, breadth-fist and depth-first search, Dijkstra’s shortest path, and random walks.
Additionally, Mango provides implementations of connected components and Chinese Whispers for clustering.
Vertices can be scored by degree, Page Rank, and random walks using one the implementations of VertexScorer
.
Finally, graphs can be written to json or GraphViz dot format and rendered using GraphViz.
3.6. Caches
Mango provides a basic set of in-memory Caches to speed up IO intensive processes.
The Cache
interface is inspired by Guava’s Cache and has methods for getting, putting, and invalidating entries.
There are currently two implemenations of Cache
: LRUCache
which keeps the last N
most recently used items and AutoCalculatingLRUCache
which extends LRUCache
to auto-calculate missing values.
3.7. Key-Value Stores
Mango provides a generic interface for key-value stores and provides in-memory and disk-backed versions.
A KeyValueStore
defines a mapping from keys to values and extends the Java Map
interface.
Additionally, a NavigableKeyValueStore
is defined in Mango that extends the Java NavigableMap
interface.
Connections to key-value stores are done through a KeyValueStoreConnection
as follows:
KeyValueStoreConnection connection = KeyValueStoreConnection.parse("kv:mem:people"); (1)
KeyValueStore<String, String> kvStore = connection.connect(); (2)
| 1 | Connections are defined by parsing a specification string defining the store. |
| 2 | The connect method of the KeyValueStoreConnection provides an instance of a KeyValueStore or NavigableKeyValueStore . |
The key-value store specification is defined as follows:
kv:(mem|disk):namespace::<PATH>?readOnly=(true|false)
Where mem
creates an in-memory key-value store and disk
a disk-based key-value store.
The namespace defines the store name an allows multiple stores to be associated with a single file.
The path is only required for disk-based key-value stores and the readOnly
parameter is optional denoting if the store is read only (this is false by default).
4. Mango Streams
Mango streams provide a common interface for working with and manipulating streams regardless of their backend implementation.
Currently, there are implementations that wrap Java’s Stream
and Spark’s RDD
classes.
Mango supports 3 types of streams:
| Stream Class | Description |
|---|---|
|
A stream of generic objects |
|
A stream of key-value pairs. |
|
A stream of double values. |
Mango provides Serializable versions of the Java functional interfaces which are used in calls to Mango streams in order to allow a common interface between Java streams and Spark streams.
|
4.1. Creating a Stream
Streams are created through a StreamingContext
.
A local streaming context is generated using StreamingContext.local()
or through StreamingContext.get(false)
whereas a distributed (Spark) contetext is retrieved by StreamingContext.distributed()
or StreamingContext.get(false)
.
Streaming contexts provide a variety of ways for creating an MStream, including the following:
| Method | Description |
|---|---|
|
Creates an empty MStream |
|
Creates an MDoubleStream over the given values. |
|
Creates an MDoubleStream from the given Java double stream. |
|
Creates an MStream by converting the array into a List. |
|
Creates an MStream over the given Iterator by treating the iterator as an Iterable. Note that local MStreams are not reusable. |
|
Creates an MStream over the given Iterable. Note that if the Iterable can be iterated over multiple times, local MStreams will be reusable. |
|
Creates an MStream over the given Stream. Note that if the Stream can be iterated over multiple times, local MStreams will be reusable. |
|
Creates a new MStream where each element is a line in the resources (recursive) at the given location. |
|
Creates a new MStream where each element is a line in the resources (recursive) at the given location. |
|
Creates a new MStream where each element is the entire content of a resource (wholeFile = true) or a single line of the resource (wholeFile = False) and resources are gathered recursively from the given location. |
|
Creates a new MStream where each element is a line in the resources (recursive) at the given location only reading files matching the given pattern. |
|
Creates an MPairStream over the collection of key-value pairs. |
|
Creates an MPairStream over the key-value pairs in the map. |
|
Creates an MPairStream over the array of key-value pairs. |
Note that Mango also implements a reusable versions of Java’s Stream classes (Stream, IntStream, DoubleStream, and LongStream).
The reusable streams use a Supplier
to provide the underlying stream.
Individual methods, i.e. map
then create a new supplier where the return stream applies the given method.
Reusable streams can be created outside of MStreams using the Streams
utility class.
4.2. Accumulators
An accumulator is a variable that can be used for aggregating values in a stream.
As with streams, accumulators are created using a streaming context, e.g. StreamingContext.local().counterAccumulator()
.
Mango provides the following accumulator implementations:
| Accumulator Class | Description |
|---|---|
|
Accumulator wrapping a Mango |
|
Accumulator wrapping a double value. |
|
Accumulator wrapping a long value. |
|
Accumulator wrapping a Java Map. |
|
Accumulator wrapping a Mango |
|
Accumulator wrapping a Java list. |
|
Accumulator wrapping a Java set. |
Accumulators can have names associated with them, which will show up in the Spark interface.
Additional accumulators can be created by implementing the base MAccumulator
interface.
| Streams should only update / modify the value of an accumulator and not try to read the value. While reading the value will work in local streams, distributed streams do not support reading. Thus, to make your logic reusable across stream types it is best to not read the values. |
4.3. Working with Streams
Working with Mango streams is very similar to working with Java streams. The core operations are:
| Operation | Description |
|---|---|
|
Transforms the items in the stream using the supplied function. |
|
Maps objects in this stream to double values |
|
Transforms the MStream into a MPairStream by transforming individual items into tuples. |
|
Transforms the items in the stream to multiple items using the supplied function. |
|
Transforms the MStream into a MPairStream by transforming individual items into multiple tuples. |
|
Filters the item in the MStream to only those for which the given Predicate evaluates to |
|
Remove duplicate items from the stream. |
|
Limits the stream to the first given number of items. |
|
Skips the first given number of items in the stream. |
|
Takes the first given number of items in the stream. |
|
Returns a new MStream containing the intersection of elements in this stream and the argument stream. |
|
Returns a new MStream containing the union of elements in this stream and the argument stream. |
Aggregation can be performed over streams using one of the following methods:
| Operation | Description |
|---|---|
|
Gets the total number of items in the stream. |
|
Provides a count per item in the stream by performing a group by. |
|
Performs a reduction on the elements of this stream using the given binary operator and given initial value. |
|
Groups the items in the stream using the given function that maps objects to key values. |
|
Performs a reduction on the elements of this stream using the given binary operator. |
|
Returns the max item in the stream requiring that the items be comparable. |
|
Returns the max item in the stream using the given comparator to compare items. |
|
Returns the min item in the stream requiring that the items be comparable. |
|
Returns the min item in the stream using the given comparator to compare items. |
Mango Streams can be converted to distrubted Spark streams by simplying calling toDistributedStream
.
Similarly, a Java stream can be created using the method javaStream
.
4.3.1. Distributed Streams and Configuration
Mango will automatically distribute the current configuration to the Spark worker nodes when using a distributed stream.
If for some reason the configuration is updated after the stream is created, you should call updateConfig()
on the distributed stream to ensure it receives the changes in configuration.
5. Reflection, Casting, and Conversion
Mango provides a number of classes and utilities for performing reflection on objects and classes and casting or converting objects from type to another.
Mango can provide a programming style seen in less strict languages, such as Python, at the cost of extra overhead.
While not best practices, this programming style can be useful for prototyping, dealing with generics, or cases where the return type is unknown.
This programming style is encapsulated in the Val
object, which represents an immutable value of possibly unknown (to us) type.
Take the following code snippet as example:
//If for some reason we do not know the return type (e.g. it returns Object) we can wrap it in a Val
Val v = Val.of(someRemoteCallThatCanReturnDifferentValues(....));
//A method that can return mulitple different types can wrap their return value in a Val
public Val computeValue(double in, boolean returnArray){
if( returnArray ){
return Val.of(new double[]{in});
}
return Val.of(in);
}
The val class provides "is" methods for determining type, e.g. isArray
, isMap
, and isPrimitiveArray
.
Additionally, you can the class information of the wrapped value using getWrappedClass
.
Val, provides convenience methods for getting the wrapped value as a number of different types, e.g. asString()
, asInteger()
, and asDoubleArray()
.
Additionally, a default value can be given to these methods in case the wrapped value is null
or cannot be converted into the given type.
Convenience methods also exist for converting into collections and maps, e.g. asSet(Type)
and asMap(Class, Class)
where the supplied type information is used to convert the elements of the collection / map.
Each of these methods make a call to as(Type)
, which attempts to convert the wrapped value into the target type returning null
if the conversion fails.
| While Val can be very useful (e.g. as the value of Map) it can be hard to debug if something goes wrong and as such should be used only when needed or prototyping code. |
5.1. Reflection
Mango aims to make using reflection a little easier.
Reflection in Mango starts with the RBase
class which defines the base set of functionality for performing reflection on an object, class, method, field, or parameter.
This base set of functionality comes in the form of querying the annotations on the reflected item and conditionally performing some action based on the presence of an annotation.
The following figure illustrates the hierarchy of classes that defines the Java reflection wrappers.
The main entry point for working with reflection in Mango is the Reflect
class.
Reflect is a wrapper around an object or class providing easy ways to access the methods, fields, constructors, and annotations on the object/class.
An instance is created using on of the static methods as follows:
// Reflecting on a class (we can only set / get / invoke static methods or create an instance)
Reflect rc = Reflect.onClass(MyClass.class);
// Reflecting on an object allows us to modify its fields and call its methods.
Reflect ro = Reflect.onObject(myClassInstance);
The Reflect instance respects scope by default. This can be changed by allowing privileged access as follows:
//Allow privileged access
ro.allowPrivilegedAccess();
//Go back to normal non-privileged access
ro.setIsPrivileged(false);
Privileged access will allow the protected and private elments of the object/class to be manipulated.
Once we have an instance of reflect we can query the object/class for its accessible fields as follows:
//Attempts to retrieve the value of a field called "name", if it cannot it will check for a getter "getName()"
String name = ro.get("name");
//We can easily set the value of a field using the set method
ro.set("name", name + "-Smith");
//Retrieves the RField for the given field name if it is accessible.
RField ageField = ro.get("age");
//Gets all accessible fields on the object
List<RField> allFields = ro.getFields();
//Gets all accessible fields that are ints
List<RField> intFields = getFieldsWhere(f -> f.getType().equals(int.class));
//Gets all accessible fields that have an annotation of MyAnnotation on them
List<RField> annotatedFields = getFieldsWithAnnotation(MyAnnotation.class);
Similarly, we can query the object/class for its accessible methods as follows:
//Retrieves the RMethod for the given method name if it is accessible.
//Note we are looking for a no-argument method
RMethod calculateAge = ro.getMethod("calculateAge");
//Retrieves the RMethod for the given method name with given parameter types if it is accessible.
//Note we are looking for a method named "doSomethingImportant" whose first argument is a String and second argument is an Integer.
RMethod doSomethingImportant = ro.getMethod("doSomethingImportant", String.class, Integer.class);
//Gets all accessible methods
List<RMethod> allMethods = ro.getMethods();
//Gets all accessible methods named "update"
List<RMethod> updateMethods = ro.getMethods("update");
//Gets all accessible methods named "update" that matching the given criteria (have 2 parameters)
List<RMethod> updateStringMethods = ro.getFieldsWhere("update", m -> m.getParameterCount()==2);
//Gets all accessible methods matching the given criteria (have 1 parameter)
List<RMethod> pseudoSetters = ro.getFieldsWhere(m -> m.getParameterCount()==1);
//Gets all accessible methods that have an annotation of MyAnnotation on them
List<RMethod> annotatedMethods = ro.getMethodsWithAnnotation(MyAnnotation.class);
Similarly, we can query the object/class for its accessible constructors as follows:
//Retrieves the RConstructor whose first parameter is an Integer and second parameter is a String.
RConstructor constructor = ro.getConstructor(Integer.class, String.class);
5.1.1. Fields, Methods, and Constructors
The RAccessibleBase
base class wrapps AccessibleObject
providing a process(CheckedFunction)
and with(CheckedConsumer)
method which automatically take care of setting the privileges of the object.
RField
implements the RAccessibleBase
and wraps a Java Field
.
The RExecutable
is child class of RAccessibleBase
that serves as a base class for reflected objects that can be "executed", e.g. Methods and Constructors.
The RExecutable
also provides ways to examine the parameters (wrapped as RParameter
) of the executable.
The RMethod
and RConstructor
classes provide methods for calling (i.e. invoking) the underlying method / constructor.
5.1.2. Getting a class from its name
The Reflect class provides two convenience static methods for getting a Class
for the name represented in a String.
The methods support the detection of arrays where the name ends with []
or starts with [L
or just [
.
Moreover, all classes in java.lang
, java.util
, and com.gengoai
can be accessed by their simple name (e.g. ArrayList).
The following code example shows the usage:
//Note this method will throw an Exception if the class is not found
Class<?> listClass = Reflect.getClassForName("ArrayList");
//This method will end up finding the class in com.gengoai.collection.counter.HashMapCounter
//Note that the "Silently" means it will return a null value if the class is not found instead of throwing an
//exception.
Class<?> counterClass = Reflect.getClassForNameSilently("collection.counter.HashMapCounter")
//int[].class
Class<?> tClass = Reflect.getClassForName("int[]");
5.1.3. Type vs Class
In many places of Mango you will find methods that can type a Java Type
or Java Class
.
A Class
is a Type
in Java, but other type implementations can be useful for dealing with generics, i.e. ParameterizedType
.
Thus, in most cases Mango will provide the option to use either a Type
or Class
.
Note that when calling a method using a Type
you either need to add the parameter type to the method call or capture the return value in a variable.
public static <T> T fromClass(Class<T> type) { ... }
public static <T> T fromType(Type type) { ... }
// OK - the compiler can guess the return type
System.out.println(fromClass(Double.class));
// NOT OK - the compiler cannot guess the return type
System.out.println(fromType(...));
Mango provides the TypeUtils
class that contains useful methods for learning more about Type
and converting them into Class
.
Additionally, Mango provides the method:
public static Type parameterizedType(Type rawType, Type... typeArguments)
to create ParameterizedType
instances so that you can store / pass with generic information.
As a convienenc, there is a parse(String)
method on TypeUtils
that will parse a string representation of a parameterized or non-parameterized type, e.g. List<String>
will be parsed into a ParameterizedType
with the raw class of List
and the type argument of String
.
This allows you to specify generic types in your configuration files when defining types.
5.2. Type Conversion
The core component of Mango’s Val
class and configuration framework is the ability to convert any arbitrary type to another.
This conversion is done using the Mango Converter
class, which utilizes a number of TypeConverter
registered using Java’s Service Loader.
A TypeConverter
defines the following:
Object convert(Object source, Type... parameters) throws TypeConversionException; (1)
Class[] getConversionType(); (2)
| 1 | Defines the methodology to convert a source of any type with the following Type parameters (used for generics). |
| 2 | Defines the classes the converter implementation can convert into. |
When converting a source object we can us the following methods:
Converter.convert(source, TARGET_TYPE); (1)
Converter.convertSilently(source, TARGET_TYPE); (2)
| 1 | A TypeConversionException will be thrown if the source object cannot be converted into the target type (e.g. trying to convert an int into a Map). |
| 2 | Returns a null value if the conversion fails. |
Mango provides many type converters out of the box which cover core Java, java.util, and Mango types.
New type converters can be registered using Java’s Service loader.
We recommend using the org.kohsuke.metainf-services
package to ease this process by only needing to add a @MetaInfServices(value = TypeConverter.class)
annotation to your type converter class.
5.3. Casting
Mango provides the Cast
class to easily cast an object.
It provides the following basic methods:
static <T> T as(Object o) (1)
static <T> T as(Object o, Class<T> clazz) (2)
| 1 | Casts an object to the desired return type throwing a java.lang.ClassCastException if the given object cannot be cast as the desired type.
This method uses an "unchecked" conversion. |
| 2 | Casts an object to a given type throwing a java.lang.ClassCastException if the given object cannot be cast as the desired type.
This method uses Class.cast . |
Additionally, there are methods for casting the elements of collections, iterables, iterators, and maps: sahi2001
static <T> Iterator<T> cast(Iterator<?> iterator)
static <T> Iterable<T> cast(Iterable<?> iterable);
static <T> Collection<T> cast(Collection<?> collection)
static <T> Set<T> cast(Set<?> set);
static <T> List<T> cast(List<?> list)
static <K, V> Map<K, V> cast(Map<?, ?> map)
The methods listed above perform casting in lazy manner and do not change the underlying data. These methods are most useful when passing an item as method parameter.
6. Input / Output
Mango provides classes for working with archive files, csv and json encoded streams, asynchronous and multi-file writers, and an abstraction around a "resource" which could be a file, url, string, etc.
6.1. Resources
A resource represents a source or destination of/for data.
It is similar in idea to Spring’s Resource class.
At the core a Resource
object facilities opening the data source for reading (InputStream
or Reader
) and/or writing (OutputStream
or Writer
) and traversing and manipulating the structure of the data source (e.g. retrieving all children of a folder or the folder for a file, deleting an element, or adding new folders).
The following is a list of the supported resource types and whether they support being read from, written to, or traversed.
| Resource Type | Readable | Writeable | Traversable | Description |
|---|---|---|---|---|
|
Wraps an expandable array of bytes for reading/writing. |
|||
|
Points to a stream resource on the classpath. |
|||
|
Special resource representing no content. |
|||
|
Wraps a Java File. |
|||
|
Wraps a Java InputStream. |
|||
|
Wraps a Java OutputStream. |
|||
|
Wraps a Java Reader. |
|||
|
Wraps System.in. |
|||
|
Wraps System.out |
|||
|
Wraps a Java StringBuilder allowing reading and writing (by overwriting the value). |
|||
|
Wraps a Java URI. |
|||
|
Wraps a Java URL. |
|||
|
Wraps a Java Writer. |
|||
|
Wraps a Java ZipFile and ZipEntry allowing reading and traversal of a zip archive. |
Resources are created by either using the constructor of one of the implementations or by using the Resources
utlility class.
The main way of creating a resource is using Resources.from(String)
where the given string defines the resource scheme.
Each scheme has an associated ResourceProvider
which takes care of parsing the scheme and creating a Resource instance.
The scheme is in the following format: PROTOCOL(?OPTIONS):PATH
where OPTIONS
is optional.
For example a FileResource
can specified using file:/home/user/file.text
.
Common options include, the charset and compression technique and are set as follows: file?compression=GZIP,charset=SJIS:/home/user/file.text
.
Note that options are set using a BeanMap thus the valid options for each resource type are the setters on that type.
The following is a list of Schemes, the generated resource type, and what the path represents for those types accessible via Resources.from(String)
:
| Scheme | ResourceType | Path |
|---|---|---|
|
|
A string which will be converted into bytes (empty is ok). |
|
|
the location of the resource found within in the default Classloader. |
|
|
the location of the resource on a local disk. |
|
|
empty. |
|
|
empty. |
|
|
the String representing the content of the resource (empty is ok). |
|
|
path of the url. |
|
|
the location on local disk where the zip file is located. |
Note that for convenience you can leave off the scheme for file resources, e.g. Resources.from("/home/user/test.csv")
will assume the given String is a FileResource
.
6.1.1. Reading
A Resource
implementation provides the following methods for reading:
| Return Value | Method | Description |
|---|---|---|
|
|
Returns true if the resource is readable, false if not. |
|
|
Opens an input stream over this resource. |
|
|
Creates an MStream (see Mang Streams) over the lines in the resource. |
|
|
Reads the resource into an array of bytes. |
|
|
OOpens a reader using guessing the encoding and falling back to the default on the resource. |
|
|
Reads the complete resource in as text breaking it into lines based on the newline character. |
|
|
Deserializes an object from a resource. |
|
|
Reads the entire resource as a String. |
One of the advantages of using a Resource
is it will automatically determine the character set of the data source when reading (except inputStream
and readBytes
).
The default charset can set using the setCharset
method.
Moreover, the resource will automatically determine if the underlying data is compressed in gzip or bzip2 format and handling it accordingly.
6.1.2. Writing
A Resource
implementation provides the following methods for writing:
| Return Value | Method | Description |
|---|---|---|
|
|
Appends the given string content to the resource. |
|
|
Appends the given byte array content to the resource. |
|
|
Returns true if the resource is writable, false if not. |
|
|
Opens an output stream over this resource. |
|
|
Writes the given byte array to the resource overwriting any existing content. |
|
|
Writes the given string to the resource overwriting any existing content. |
|
|
Serializes an object to the resource using Java Serialization. |
|
|
Opens a writer for writing to the resource. |
6.2. Resource Monitoring
A common pitfall in Java is not properly closing resources.
This can become especially tricky when dealing with concurrency and the new Java stream framework.
Mango provides a ResourceMonitor
which tracks MonitoredObjects
and automatically closes (frees) them when they are no longer referenced.
The ResourceMonitor
is basically a garbage collector for resources!
The ResourceMonitor
class provides convenience methods for monitoring the most common types:
SQL Connection |
InputStream |
OutputStream |
Reader |
Writer |
Stream<T> |
MStream<T> |
DoubleStream |
IntStream |
LongStream |
Additionally, it provides a generic monitor
method that takes an Object
and returns a MonitoredObject
wrapping the given object.
For generic Objects you can also specify a custom procedure to run when the resource is "closed" by passing in Consumer<T>
that will free resources.
An example of creating a Monitored object from a custom class is as follows:
MonitoredObject<MyClass> m = ResourceMonitor.monitor(new MyClass(), mc -> {
//special on-close stuff here
});
System.out.println(m.object.getValue());
The object is wrapped in a MonitoredObject
which is tracked by the resource monitor.
We have specified a custom on-close operation, which will be called when there are no other references to the wrapped MyClass
object.
The wrapped object is accessed via the public field object
6.3. CSV
Delimited Separated Value (DSV) files, where the delimiter is most commonly a comma or tab, are widely used data format for everything from finance to to-do lists. Mango provides a reader, writer, and formatter for DSV which is configurable to match most standards. The following code snippet illustrates how easy it is to read in a CSV file:
try( CSVReader reader = CSV.csv().reader(Resources.from("/data/people.csv")) ){
List<String> row;
while( (row = reader.nextRow()) != null ){
System.out.println(row);
}
}
The CSV format can be specified using fluent accessors on the CSV
class.
A generic CSV and TSV format are accessible via csv()
and tsv()
respectively, but one can also call builder()
which will use default values.
You can instruct the reader that the first line of a CSV file is the header by calling hasHeader()
on your CSV object.
Alternatively, you can specify the header if one is not given in the file using header(String…)
or header(List<String>)
.
When a header is specified you can iterate over the file using: CSV.rowMapStream()
which will provide Java stream of Map<String,String>
.
6.4. JSON
Mango uses Jackson for handling JSON.
Mango provides a utility class Json
to perform basic operations, such as serializing an object to a JSon string or to a resource and deserializing Json into an Object.
Additionally, Mango provides a JsonEntry
class that wraps the Jackson Json classes allowing easy builder style approaches to constructing Json.
6.5. Specifications
The builder pattern is an excellent way to create Objects which have multiple parameters.
However, the builder pattern doesn’t help when we want to specify parameters via configuration or in a concise manner.
That is where Mango Specificatons come in handy.
A specification is a URI-like object defining a Schema
, Protocol
, SubProtocols
, Path
, and Query Parameters
that define a resource, connection, etc.
The specification form is as follows:
SCHEMA:(PROTOCOL(:SUB-PROTOCOL)*)?(::PATH)?(;query=value)
An example is kv:mem:people
which defines an in-memory ke-value store with the namespace people.
The specifciation kv:disk:people::~/people.db;readOnly=true
defines a disk-based key-value store with the namespace people stored at ~/people.db
and being accessed as read only.
Note that the Path and Query Arguments can will be resolved against the current Config allowing for dynamic paths like ${BASE_DIR}/myFile
for paths and parameter=${parameter.defaultValue}
where ${BASE_DIR}
and ${parameter.defaultValue}
will be set via the Config.
7. Pseudo-Language Extensions
Mango provides a number of classes and utilities that act as extensions / enhancements to Java concepts. We call these enhancements "pseudo-language extensions" as Java does not not provide an easy way of extending the language. In many cases these extensions were created for specific use cases in the Hermes and Apollo libraries.
7.1. Dynamic Enumerations
Dynamic enumerations are an enum-like objects that can have elements defined at runtime.
Elements on a dynamic enumeration are singleton objects.
In most cases it is acceptable to use the ==
operator for checking equality.
There are two types of dynamic enumerations:
-
Flat enums - act in the same manner as Java enums
-
Hierarchical enums - each value is capable of having a single parent forming a tree structure with a single ROOT.
Both flat and hierarchical enums are uniquely defined by the label used to make them. Labels are restricted to only containing letters, digits, and underscores. Further, all labels are normalized to uppercase. Note that all labels should be unique within the dynamic enumeration.
Dynamic enumeration elements implement the Tag
interface, which defines the name()
, label()
, and isInstance(Tag)
methods.
For flat enum elements these methods are all based on its normalized label, i.e. name()
and label()
return the normalized label and isInstance(Tag)
checks that the given tag is of the same class and then checks for label name equality.
However, hierarchical enum elements are defined with a label and a parent.
Therefore, the name()
method of hierarchical enum elements returns the full path from the ROOT (but not including the ROOT), e.g. if we have an element with label ScienceTeacher
whose parent is Teacher
which has ROOT as the parent, the name would be Teacher$ScienceTeacher
.
The isInstance(Tag)
method will travese the hierarchy, such that the method would return true if we ask if Teacher$ScienceTeacher
is an instance of Teacher
.
7.1.1. Generating Dynamic Enumerations
The main method of the EnumValue
class provides cli interface for bootstraping the creation of a dynamic enumeration.
Usage is as follows:
java EnumValue --className=<Name of Enum> --packageName=<Package to put the Class in> --src=<Source directory>
The generated class will be placed in the provided source folder under the given package name.
Optionally, a -t
parameter can be passed to the command line to generate a hierarchical enum.
Core to the definition of both flat and hierarchical enumerations are:
-
Registry - The registry stores the defined elements.
-
public static Collection<Colors> values() - Acts the same as the
values()
method on a Java enum. -
public static Colors valueOf(String name) - Acts the same as the
valueOf(String)
method on a Java enum.
In addition, the following make method is defined for flat enumerations: public static TYPE make(String name)
The following make method is defined for hierarchical enumerations: public static TYPE make(TYPE parent, String name)
The supplied methods should not be removed. It is possible to update the logic to suit your needs, but removing the methods all together can result in problems.
7.1.2. Defining Elements
We can define elements by adding static final variables like the following for flat enumerations:
public static final Colors RED = make("RED");
public static final Colors BLUE = make("BLUE");
and the following for hierarchical enumerations:
public static final Entity ANIMAL = make(ROOT,"ANIMAL");
public static final Entity CANINE = make(ANIMAL,"CANINE");
In the case of hierarchical dynamic enumerations or flat enumerations that require other information, it is useful to use the Preload annotation on the class defining the elements. This will ensure that the elements are initialized at startup when using the Mango application.
7.2. Parameter Maps
Parameter maps are specialized maps that have predefined set of keys (parameters) where each key has an associated type and default value.
They are useful to simulate "named and default parameters" found in other languages like Python.
However, parameters defined in a parameter map are typed and will validate valeus of the correct type are being assigned.
Parameter maps are implemented using the ParamMap
class.
In order to define a ParamMap
, you must first define the parameters.
The first step is to construct a parameter definition (ParameterDef
) that maps a parameter name to a type.
Parameter definitions can be used by multiple ParamMap
.
To construct a ParameterDef
, we use one of the static methods as such:
public static final ParameterDef<String> STRING_PARAMETER = ParameterDef.strParam("stringParameter");
public static final ParameterDef<Boolean> BOOLEAN_PARAMETER = ParameterDef.boolParam("booleanParameter");
With the parameters defined, we can now create a parameter map.
Typically, you will want to subclass the ParamMap
class setting its generic type to the class you are creating.
You will want to define a set of public final variables of type Parameter
that will map a parameter definition to a value.
Each of the parameters has a default value associated with it, such that whenever the parameter map is used the calling method can be assured that a reasonable value for a parameter will be set.
The following example illustrates the definition of a MyParameters
parameter map with two parameters.
public class MyParameters extends ParamMap<MyParameters> {
public final Parameter<String> stringParameter = parameter(STRING_PARAMETER, "DEFAULT");
public final Parameter<Boolean> booleanParameter = parameter(BOOLEAN_PARAMETER, true);
}
Now we can define methods that utilize our MyParameters
class.
We can define the method to take a MyParameters
object or to take a Consumer
.
Examples of this are as follows:
public void myMethod(MyParameters parameters) {
System.out.println(parameters.<String>get(STRING_PARAMETER));
System.out.println(parameters.<Boolean>get(BOOLEAN_PARAMETER));
}
public void myMethod2(Consumer<MyParameters> consumer) {
myMethod(new MyParameters().update(consumer));
}
ParamMap
have fluent accessors, so that we when using them as the argument to myMethod
, we can do the following:
myMethod(new MyParameters().set(STRING_PARAMETER, "Set")
.set(BOOLEAN_PARAMETER, false));
We can also use the public fields directly:
myMethod(new MyParameters().stringParameter.set("SET")
.booleanParameter.set(false));
The myMethod2
illustrates how we can mimic named parameters using `Consumer`s.
Whe can call the method in the following manner:
myMethod2($ -> {
$.stringParameter.set("Now is the time");
$.booleanParameter.set(true);
});
//Or via fluent accessors
myMethod2($ -> $.stringParameter.set("Now is the time")
.booleanParameter.set(true));
In addition to using the public variable, we can also set a parameter’s value using its name as follows:
myMethod2(p -> {
p.set("stringParameter", "Now is the time");
p.set("booleanParameter", true);
});
You can use inheritance to specialize your parameter maps, for example:
public abstract class BaseParameters<V extends BaseParameters<V> extends ParamMap<V> {
public final Parameter<Integer> iterations = parameter(ITERATIONS, 100);
}
public class ClusterParameters extends BaseParameters<ClusterParameters> {
public final Parameter<Integer> K = parameter(K, 2);
}
public class ClassifierParameters extends BaseParameters<ClassifierParameters> {
public final Parameter<Integer> labelSize = parameter(LABEL_SIZE, 2);
}
Creates an abstract base parameter class (BaseParameters
) which defines common parameters (iterations
).
Child classes (ClusterParameters
and ClassifierParameters
) then can add parameters specific to their use case.
We can then construct a method which takes the BaseParameters
, e.g. train(BaseParameters<?> parameters)
which we during invocation we can send the correct set of parameters.
//Option 1 use the as method
public void train(BaseParameters<?> parameters) {
ClassifierParameters cParameters = parameters.as(ClassifierParameters.class);
int iterations = cParameters.get(ITERATIONS);
int labelSize = cParameters.get(LABEL_SIZE);
}
//Option 2 use the getOrDefault methods
public void train(BaseParameters<?> parameters) {
int iterations = parameters.get(ITERATIONS);
int labelSize = parameters.getOrDefault(LABEL_SIZE,2);
}
When using the BaseParameters
class we can cast the class to the correct instance type (e.g. ClassifierParameters
) as shown in option 1 or use the getOrDefault
methods on the ParamMap
as shown in option2.
7.3. Tuples
A tuple is a finite sequence of items.
Mango provides specific implementations for degree 0-4 tuples, which all each element’s type to be defined via generics.
For tuples with degree 5 or more, a generic NTuple
is provided.
9. Application Framework
The application framework takes away much of the boilerplate in creating a command line or gui application, such as initializing configuration and command line parsing.
Application has three abstract implementations: CommandLineApplication
and SwingApplication
(mango-swing).
While Similar there are small differences in the use of these classes.
The following is an example of a command line application:
@Application.Description("My application example")
public class MyApplication extends CommandLineApplication {
@Option(description = "The user name", required = true, aliases={"n"} )
String userName
@Option(name="age", description="The user age", required=true, aliases={"a"})
int userAge
@Override
protected void programLogic() throws Exception {
System.out.println("Hello " + userName + "! You are " + userAge + " years old!");
}
public static void main(String[] args){
new MyApplication.run(args);
}
}
The sample MyApplication class extends the CommandLineApplication
class.
Command line applications implement their logic in the programLogic method and should have the run(args[])
method called in the main method.
The super class takes care of converting command line arguments into local fields on MyApplication using the @Option
annotation (for information on the specification see Command Line Parsing).
@Option
annotations that do not have a name set use the field name as the command line option (e.g. --userName
in the example above).
In addition, the global ''Config'' (see Configuration for more information) instance is initialized using default configuration file associated with the package of the application.
By default the application name is set to the class name.
Note: the application name and associated default config package can be specified via a constructor by calling super.
A simple Swing application is defined as follows:
@Application.Description("My application example")
public class MySwingApplication extends SwingApplication {
@Option(description = "The user name", required = true, aliases={"n"} )
String userName
@Option(name="age", description="The user age", required=true aliases={"a"})
int userAge
@Override
public void setup() {
//prepare your GUI
}
public static void main(String[] args){
new MySwingApplication.run(args);
}
}
Swing applications require the mango-swing
libreary.
9.1. Command Line Parsing
Mango provides a posix-like command line parser that is capable of handling non-specified arguments.
Command line arguments can be specified manually adding by adding a NamedOption
via the addOption(NamedOption)
method or automatically based on fields with @Option
annotations by setting the parser’s owner
object via the constructor.
The parser accepts long (e.g. --longOption
) and short (e.g. -s
) arguments.
Multiple short (e.g. single character) arguments can be specified at one time (e.g. -xzf
would set the x, z, and f options to true).
Short arguments may have values (e.g. -f FILENAME
).
Long arguments whose values are not defined as being boolean require their value to be set.
Boolean valued long arguments can specified without the true/false value.
All parsers will have help (-h
or --help
), config (--config
), and explain config (--config-explain
) options added automatically.>
Values for options will be specified on the corresponding NamedOption
instance.
The value can be retrieved either directly from the NamedOption
or by using the get(String)
method.
Argument names need not specify the --
or -
prefix.
An example of manually building a CommandLineParser is listed below:
CommandLineParser parser = new CommandLineParser();
parser.addOption(NamedOption.builder()
.name("arg1")
.description("dummy")
.required(true)
.type(String.class)
.build()
);
String[] notParsed = parser.parse(args)
An example of using fields to define your command line arguments is as follows:
public class MyMain {
@Option(description="The input file", required=true, aliases={"i"})
String input;
@Option(name ="l", description="Convert input to lowercase", default="false")
boolean lowerCase;
public static void main(String[] args){
MyMain app = new MyMain();
CommandLineParser parser = new CommandLineParser(app);
}
}
9.2. Configuration
The configuration format is a mix between json and java properties format. The need to know features are:
-
The global Config object accesses properties from config files, the command line, and environment variables
-
Comments with
#
-
Property names can be a combination of letters, digits, ".", and "_"
-
Properties and their values are separated using = or :
-
Property values can be referenced using
${propertyName}
-
Beans can be referenced using
@{beanName}
-
Properties can be appended to using
+=
-
The
\
is used to escape characters in property value (especially useful for whitespace at the beginning of a value) -
The
\
at the end of a line with no spaces after it indicates a multiline property value (Same as java properties) -
Other config files can be imported using @import for example
@import com/mycompany/myapp/myconf.conf
by default the resource is considered to be a classpath resource
9.2.1. Sections
Sections avoid the need to retype the same prefix multiple times. For example:
remote {
apis {
search = google
translate = bing
}
storage {
text = s3
search = solr
}
}
would equate to the following individual properties being set:
tools.api.search = google
tools.api.translate = bing
tools.storage.text = s3
tools.storage.search = solr
9.2.2. Beans
Beans can be defined as follows:
ParentJohn {
singleton=true
class=com.mycompany.app.Parent
constructor {
param1 {
type = String
value = John
}
param2 {
type = String[]
value = Same,Ryan,Billy
}
}
}
10. Helpful Utilities, Classes, and Interfaces
|
The Copyable interface defines a method for returning a copy of an object. Individual implementations are left to determine if the copy is deep or shallow. However, a preference is for deep copies. |
|
Convenience methods for encryption with common algorithms. |
|
Enumeration of world languages with helpful information on whether or not the language is Whitespace delimited or if language is read right to left (May not be complete) |
|
Tracks start and ending times to determine total time taken. (Not Thread Safe) |
|
Tracks start and ending times to determine total time taken. (Thread Safe) |
|
Mimics |
|
Lazily create a value in a thread safe manner. |
|
Convenience methods for validating method arguments. |


Enter the name of the event.
The Event must contain at least 1 character.
Enter the date of the event.


Dynamic array based on segments of exponential growing size. More...
Go to the source code of this file.
Data Structures | |
| struct | tommy_array_struct |
| Array container type. More... | |
Defines | |
| #define | TOMMY_ARRAY_BIT 6 |
| Initial and minimal size of the array expressed as a power of 2. | |
Typedefs | |
| typedef struct tommy_array_struct | tommy_array |
| Array container type. | |
Functions | |
| void | tommy_array_init (tommy_array *array) |
| Initializes the array. | |
| void | tommy_array_done (tommy_array *array) |
| Deinitializes the array. | |
| void | tommy_array_grow (tommy_array *array, tommy_count_t size) |
| Grows the size up to the specified value. | |
| void ** | tommy_array_ref (tommy_array *array, tommy_count_t pos) |
| Gets a reference of the element at the specified position. | |
| void | tommy_array_set (tommy_array *array, tommy_count_t pos, void *element) |
| Sets the element at the specified position. | |
| void * | tommy_array_get (tommy_array *array, tommy_count_t pos) |
| Gets the element at the specified position. | |
| void | tommy_array_insert (tommy_array *array, void *element) |
| Grows and inserts a new element at the end of the array. | |
| tommy_count_t | tommy_array_size (tommy_array *array) |
| Gets the initialized size of the array. | |
| tommy_size_t | tommy_array_memory_usage (tommy_array *array) |
| Gets the size of allocated memory. |
Dynamic array based on segments of exponential growing size.
This array is able to grow dynamically upon request, without any reallocation.
The grow operation involves an allocation of a new array segment, without reallocating the already used memory, and then not increasing the heap fragmentation. This also implies that the address of the stored elements never change.
Allocated segments grow in size exponentially.
| #define TOMMY_ARRAY_BIT 6 |
Initial and minimal size of the array expressed as a power of 2.
The initial size is 2^TOMMY_ARRAY_BIT.
| typedef struct tommy_array_struct tommy_array |
Array container type.
| void tommy_array_init | ( | tommy_array * | array | ) |
Initializes the array.
| void tommy_array_done | ( | tommy_array * | array | ) |
Deinitializes the array.
| void tommy_array_grow | ( | tommy_array * | array, |
| tommy_count_t | size | ||
| ) |
Grows the size up to the specified value.
All the new elements in the array are initialized with the 0 value.
| void** tommy_array_ref | ( | tommy_array * | array, |
| tommy_count_t | pos | ||
| ) |
Gets a reference of the element at the specified position.
You must be sure that space for this position is already allocated calling tommy_array_grow().
| void tommy_array_set | ( | tommy_array * | array, |
| tommy_count_t | pos, | ||
| void * | element | ||
| ) |
Sets the element at the specified position.
You must be sure that space for this position is already allocated calling tommy_array_grow().
| void* tommy_array_get | ( | tommy_array * | array, |
| tommy_count_t | pos | ||
| ) |
Gets the element at the specified position.
You must be sure that space for this position is already allocated calling tommy_array_grow().
| void tommy_array_insert | ( | tommy_array * | array, |
| void * | element | ||
| ) |
Grows and inserts a new element at the end of the array.
| tommy_count_t tommy_array_size | ( | tommy_array * | array | ) |
Gets the initialized size of the array.
| tommy_size_t tommy_array_memory_usage | ( | tommy_array * | array | ) |
Gets the size of allocated memory.


Assuming stack is a class, this creates a stack object and places its location in q and p. The compiler will not allow a call to stack's exported subprograms using p directly, as in:
An assignment from p to q is legal, as in:
This implies a run time check to make sure that p locates an object that is a stack (or a descendant of a stack).
Here is a way to call a subprogram exported from stack using p:
This checks to see that p locates a stack object (or a descendant) before calling the stack operation push.
var p : pointer to anyclass % Short form: var p : ^ anyclass
var q : pointer to stack % Short form: var q : ^ stack
new q % Create a stack object
p := q % Legal because p's class
% is an ancestor of q's class
p -> push (14) % ILLEGAL! anyclass has no operations
q := p % Checks that p locates a stack object (or descendant)
stack (p) . push (14) % Checks that p locates a stack object
See also class. See also export list, import list, inherit list, implement list and implement by list.


Moving to Italy - To do list
Make an Italian Berlitz course.
Move to Italy.
Have a yard sale.
Pack what's left.
Ship boxes.
Jump on plane.
Say "Ciao!" upon landing.


Welcome! This is Sandy’s take on making a simple yet powerful enough HTTP library. Inspired by python’s requests.
When it comes to making network requests, I find myself writing a lot of repetitive go code, you know the gist of getting a json response,
ctx := context.WithTimeout(context.TODO(), time.Minute)
req, err := http.NewRequestWithContext(ctx, method, URLpath, body)
if err != nil { /* ... */ }
params := req.URL.Query()
params.Add(key, value)
// more great parameters you need
req.URL.RawQuery = params.Encode()
resp, err := client.Do(req)
if err != nil { /* ... */ }
defer resp.Body.Close()
// do a response status check if needed...
ans := &SomeStruct{}
if err != json.NewDecoder(resp.Body).Decode(ans); err != nil { /*... */ }
// whatever other magic you need to do!
This is still a condensed version! The example above skips a couple of steps for brevity, like setting timeouts, deadlines, proper reading, buffering, progress, etc.
You can end up making something of your own, but repeating the same code has many issues, such as forgetting to close the response body or set proper contexts with plenty more.
What if instead, all you had to write was
ans := &SomeStruct{}
err := haruhi.URL(URLpath).
Method(method).
Params(params).
Body(body).
Timeout(time.Minute).
ResponseJSON(ans)
and it did everything for you? You can even simplify it with haruhi’s sensible defaults, such as running a GET
request by default, etc, so you could even do
respStr, err := haruhi.URL(url).Get()
Haruhi of course, supports more funtionality that is aimed to be simple and straight-forward. Entire codebase is documented, so head on to go docs to see what else she can do.
Have fun requesting!
Please visit the github page and let me know through issues or PRs if you have any questions!


Barça's Abel Ruiz: If there are no opportunities, you have to look elsewhere
The young striker spoke to EFE while with the Spain U21 squad in Madrid
by FEAbel Ruiz (Valencia, 2000) says he will give his all to make it at Barcelona but admitted he could be forced to look elsewhere if his chance in the first team does not arrive.
The Barça B striker, speaking to EFE from the Spain U21 camp, had options to leave in the summer but opted to remain with the club's reserve team in the third division.
He's happy with that choice for now but sooner or later -- in the winter or next summer -- he may have to decide what's best for his future.
"It's not that I didn't want to stay," he said. "I have always said that my first choice is Barça but it's true that if you want to keep growing and improving you have to look for what's best for you.
"In this case, the decision was to stay in Segunda B and keep growing as a player and person while waiting for chances in the first team.
"I work day-to-day and take things step-by-step. I think the secret is to take things slowly. The opportunities will arrive and you have to be ready, which is what we are all trying in the academy.
"I have always said that I want to be at Barcelona and I want to grow as a player and person at this club because they've given me everything since day one.
"As long as they have confidence in me, I am going to have confidence in them but if in the end you don't enjoy the type of opportunities you desire, you have to look elsewhere for those minutes and competitions."
One player who has had first team chances this season is Ansu Fati, who is also in the Spain U21 squad along with Ruiz.
"He's a young kid, much younger than me even," Ruiz said of the 17-year-old. "I've been lucky to have him close in La Masia and I've been with him for four or five years, even sharing a room with him and I am so delighted (for the success he's had)."


Tutorial 2 - Launching Maqetta
When going through Maqetta's tutorials, it is suggested that you have two side-by-side
browser windows open, one showing the tutorial, and the other where you run the application
and perform the steps listed in the tutorial.
Topics covered:
- Different ways to launch the Maqetta application
- Run the Maqetta application at Maqetta.org
- Run the Maqetta application locally (i.e., local install)
- Install on a server (e.g., intranet server)
Different ways to launch the Maqetta application
You can launch the Maqetta application in the following ways:
- Maqetta.org - You can run Maqetta by simply
going to Maqetta.org and then clicking
on the "Launch Maqetta" button. The Maqetta team
attempts to keep the application running and tries to ensure
that the server has reasonable performance, but the application
at Maqetta.org is available on an as-is basis with no guarantees
about data preservation (e.g., you have to back up your own data)
or security.
- Local install -
You can download either the latest stable release or
last night's nightly build, and then install on your own computer.
This option provides best performance, but you won't be
able to easily share your mockups with your colleagues.
- Intranet server install -
Your company can download the latest stable release,
and then install on an intranet server behind your company's firewall,
and potentially integrate with a Java application server
and your company's LDAP for user authentication.
Also, it is possible for site administrators to customize
your company's version of Maqetta
to support your company's widgets and themes.
The sections below walk you through the getting start process for each of the above options.
Run the Maqetta application at Maqetta.org
You can run the Maqetta application by simply
going to Maqetta.org and then clicking
on the "Launch Maqetta" button.
This will take you to the login screen.
New users will need to click on the Register button (at the bottom of the previous snapshot),
which will take you to the Register screen.
Enter your email address and click "Sign up".
It is VERY IMPORTANT that you enter a valid email address and make sure that
you typed the email address correctly. You will not be able to complete
registration if you enter an incorrect or invalid email address.
An activation email will be sent to your email address. Clicking on the hyperlink in the email
will take you back to Maqetta.org, to the create account screen, where you can enter your Maqetta.org password:
After clicking on "Sign up", you will enter the Maqetta application.
Run the Maqetta application locally (i.e., local install)
With this option, you perform these steps:
- Download a ZIP file that contains the Maqetta application (see notes below)
- Unzip onto your local filesystem
- Double-click on a launch script to start up the Maqetta application
(running as a local web server, with default port of 50000)
- Enter an appropriate URL
(such as http://localhost:50000/maqetta)
into the browser's address bar.
If you want to download the public release of Maqetta from
Maqetta.org, you have two options:
If your company has installed Maqetta on its own servers, they might also provide
a ZIP file that you can download, where that downloadable Maqetta might include
your company's widgets and themes.
After expanding (unzipping) the ZIP file, there will be a readme.html
file
that contains detailed descriptions of system pre-requisites and launch instructions.
Many users, however, can simply:
- Double-click on the appropriate launch script
(
maqetta.server.win.bat
for Windows, maqetta.server.mac.command
for Mac)
- (After waiting for the launch script to complete) Type
http://localhost:50000/maqetta
into the browser's address bar.
If you downloaded the ZIP from Maqetta.org, you will be presented with the following screen:
The first time you run a local install download from Maqetta.org,
you will need to click on the "Register" button
(see the bottom of the above picture)
to create a user account and password.
After you click "Register", you should see this screen:
In the above picture, you need to enter a valid email address and your password.
Once you have created a user account, in the future you can just enter that user account and password
onto the login screen - you only need to "Register" once.
Be sure to remember your login and password. There is no way to retrieve or reset
your logins or passwords for a local install.
Install on a server (e.g., intranet server)
The Maqetta team provides detailed instructions for setting up Maqetta to run
on a Unix server. Maqetta will probably run on other servers (e.g., Windows or Mac),
but you might have to figure some things out on your own.
This option follows many of the same steps as the local install option.
- Download a ZIP file that contains the Maqetta application (see notes below)
- Unzip onto your server's filesystem
- Customize the configuration files to match your requirements
- Set up your server to launch Maqetta (and relaunch at server start time)
After setting up the configuration settings and starting the Maqetta server,
users will be able to run Maqetta by entering http://yourserver:port/path-to-maqetta
into the browser address bar.
Previous / Next


{% extends "website/framework/base_success.html" %} {% block message %} Issue {{ issue.name }} has been created successfully for repository {{ repository.name }}. {% endblock %} {% block javascript %} location.reload(); {% endblock %}


Method references in Java 8 allows us to convert a call to a method
or a constructor into instance of functional interface.
For simple lambda expressions like x -> x.foo() using method
references results in expression FooClass::foo that is more
clear and readable (if this is your first encounter with method
references you may feel that they are more complicated than
lambdas - don’t worry most people go through this stage,
after a while you get used to them and you will start to
appreciate their beauty).
We will start by demonstrating how to use method references
to call instance methods.
A lambda expression of form (ObjClass obj) -> obj.method() is
equivalent to method reference ObjClass::method, for example:
Another kind of lambda expressions that can be changed to method references
has form arg -> someObj.method(arg), here the instance on which method is
called is constant but the argument changes. Let’s continue our example
with Persons:
This aproach also works with methods that have more than one parameter:
When we provide both instance on which to call a method and all method
arguments we may use method references too:
Using method references when working with static methods is also easy,
for example:
Now let’s move to constructor references.
Every lambda expression in form () -> new FooClass() can be
rewritten to use constructor reference as FooClass::new, for example:
We may even use constructor references to create arrays:
The last example that I want to present illustrates how
to use method references to refer to super class methods:
So after all this examples it’s your turn now, launch your favorite IDE
and write some Java code with method references!


About us
Founded in 2014, SIMPLEX I.T is a Bangladesh-headquartered provider of IT consulting services and custom software development with 10+ IT professionals located internationally.
For over 5 years we’ve been bringing custom and platform-based solutions to large and midsized companies in Healthcare, Retail, Telecom and other industries. Market Access Group, Sothern CNG, Mac-Nels BD, Hanif Paribahan, Democracy Watch, KTS Logistics, KL Design along with other influencers rely on our solutions in their daily operations.


Home
> Popovers
Click to toggle popover
Four directions
Popover on top
Popover on right
Popover on bottom
Popover on left
Dismiss on next click
Dismissible popover
Disabled elements
Disabled button


2 writes to Members
System.Management.Automation (2)
engine\parser\ast.cs (2)
2582
Members
= new ReadOnlyCollection<MemberAst>(members.ToArray());
2587
Members
= s_emptyMembersCollection;
16 references to Members
System.Management.Automation (16)
DscSupport\CimDSCParser.cs (3)
2344
enumNames = propTypeName._typeDefinitionAst.
Members
.Select(static m => m.Name).ToArray();
2432
foreach (var member in typeDefinitionAst.
Members
)
2513
foreach (var member in typeDefinitionAst.
Members
)
engine\parser\ast.cs (5)
2583
SetParents(
Members
);
2670
return new TypeDefinitionAst(Extent, Name, CopyElements(Attributes), CopyElements(
Members
), TypeAttributes, CopyElements(BaseTypes));
2726
for (int index = 0; index <
Members
.Count; index++)
2728
var member =
Members
[index];
8307
foreach (var member in _typeDefinitionAst.
Members
)
engine\parser\Compiler.cs (1)
2939
foreach (var propertyMember in _memberFunctionType.
Members
.OfType<PropertyMemberAst>())
engine\parser\PSType.cs (2)
488
foreach (var member in _typeDefinitionAst.
Members
)
1203
foreach (var member in _enumDefinitionAst.
Members
)
engine\parser\SemanticChecks.cs (2)
1500
foreach (var member in typeDefinitionAst.
Members
)
1610
foreach (var member in baseTypeDefinitionAst.
Members
)
engine\parser\SymbolResolver.cs (1)
67
foreach (var member in typeDefinition.
Members
)
engine\parser\TypeInferenceVisitor.cs (1)
291
foreach (var member in typename.TypeDefinitionAst.
Members
)
engine\PSClassSearcher.cs (1)
298
foreach (var member in statement.
Members
)


java.lang.Object Main
public class Main
Class main contains all the methods necessary to run my simplified version of Conway's Game of Life.
| Constructor Summary | |
|---|---|
Main()
|
| Method Summary | |
|---|---|
static boolean |
boundsChecker(boolean[][] map,
int x,
int y)
Method boundsChecker is a bounds checking method that makes sure that the program and all its methods remain within the alotted boundaries. |
static void |
displayGrid(boolean[][] grid)
Method displayGrid looks at each cell and then gives it a dead(.) or alive(*) value |
static boolean[][] |
generation()
Method generation is a method which creates the 2D array |
static void |
killProgram(int until)
Method killProgram is a method that will stop the program after a certain amount of time This method was only created because the program will not end on its own. |
static void |
main()
Method main runs playGame(); |
static void |
message()
Method message concatonates several strings and displays it to the user prior to running the program. |
static boolean |
neighborCheck(int nosNeighbors,
boolean alive)
Method neighborCheck is a method which selects each cell and goes through several conditions to determine whether or not the cell should be dead or alive in the following generation |
static int |
neighborCounter(boolean[][] grid,
int left,
int down)
Method neighborCounter is a method which runs several conditions to count the number of neighbors that exist for the selected cell |
static boolean[][] |
nextGeneration(boolean[][] map)
Method nextGeneration is a method that uses the data collected in neighborCounter, neighborCheck & boundsChecker to create the grid for the next generation |
static void |
playGame()
Method playGame runs all the methods and displays the program in the console window |
| Methods inherited from class |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Constructor Detail |
|---|
public Main()
| Method Detail |
|---|
public static boolean boundsChecker(boolean[][] map, int x, int y)
map
- A parameter which is the 2D array printed in the console windowx
- A parameter which is an int which represents all the cells in the x-plane of the arrayy
- A parameter which is an int that represents cells when going through the y-plane
of the array
public static void displayGrid(boolean[][] grid)
grid
- A parameter which is the 2D array on which the program is displayedpublic static boolean[][] generation()
public static void killProgram(int until)
public static void main()
public static void message()
public static boolean neighborCheck(int nosNeighbors, boolean alive)
nosNeighbors
- an integer which holds the number of neighbors for the selected cellalive
- a boolean value which has two states: Alive and Dead
public static int neighborCounter(boolean[][] grid, int left, int down)
grid
- A parameter which is the 2D array that we see in the console windowrow
- A parameter which is an integer that takes us through each rowcol
- A parameter which is an integer that takes us through each column. This int along
with the int row ends up going through each cell in the 30X30 array
public static boolean[][] nextGeneration(boolean[][] map)
map
- A parameter which is a 2D array which encompasses the whole map
public static void playGame()


DROP TABLE
Removes a table from a database. Only the owner of the table, the schema owner, or a superuser can drop a table.
If you are trying to empty a table of rows, without removing the table, use the DELETE or TRUNCATE command.
DROP TABLE removes constraints that exist on the target table. Multiple tables can be removed with a single DROP TABLE command.
DROP TABLE with an external table can't be used inside a transaction (BEGIN … END).
Syntax
DROP TABLE [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
Parameters
- IF EXISTS
-
Clause that indicates that if the specified table doesn’t exist, the command should make no changes and return a message that the table doesn't exist, rather than terminating with an error.
This clause is useful when scripting, so the script doesn’t fail if DROP TABLE runs against a nonexistent table.
- name
-
Name of the table to drop.
- CASCADE
-
Clause that indicates to automatically drop objects that depend on the table, such as views.
To create a view that is not dependent on a table referenced by the view, include the WITH NO SCHEMA BINDING clause in the view definition. For more information, see CREATE VIEW.
- RESTRICT
-
Clause that indicates not to drop the table if any objects depend on it. This action is the default.
Examples
Dropping a Table with No Dependencies
The following example creates and drops a table called FEEDBACK that has no dependencies:
create table feedback(a int); drop table feedback;
If a table contains columns that are referenced by views or other tables, Amazon Redshift displays a message such as the following.
Invalid operation: cannot drop table feedback because other objects depend on it
Dropping Two Tables Simultaneously
The following command set creates a FEEDBACK table and a BUYERS table and then drops both tables with a single command:
create table feedback(a int); create table buyers(a int); drop table feedback, buyers;
Dropping a Table with a Dependency
The following steps show how to drop a table called FEEDBACK using the CASCADE switch.
First, create a simple table called FEEDBACK using the CREATE TABLE command:
create table feedback(a int);
Next, use the CREATE VIEW command to create a view called FEEDBACK_VIEW that relies on the table FEEDBACK:
create view feedback_view as select * from feedback;
The following example drops the table FEEDBACK and also drops the view FEEDBACK_VIEW, because FEEDBACK_VIEW is dependent on the table FEEDBACK:
drop table feedback cascade;
Viewing the Dependencies for a Table
You can create a view that holds the dependency information for all of the tables in a database. Before dropping a given table, query this view to determine if the table has dependencies.
Type the following command to create a FIND_DEPEND view, which joins dependencies with object references:
create view find_depend as select distinct c_p.oid as tbloid, n_p.nspname as schemaname, c_p.relname as name, n_c.nspname as refbyschemaname, c_c.relname as refbyname, c_c.oid as viewoid from pg_catalog.pg_class c_p join pg_catalog.pg_depend d_p on c_p.relfilenode = d_p.refobjid join pg_catalog.pg_depend d_c on d_p.objid = d_c.objid join pg_catalog.pg_class c_c on d_c.refobjid = c_c.relfilenode left outer join pg_namespace n_p on c_p.relnamespace = n_p.oid left outer join pg_namespace n_c on c_c.relnamespace = n_c.oid where d_c.deptype = 'i'::"char" and c_c.relkind = 'v'::"char";
Now create a SALES_VIEW from the SALES table:
create view sales_view as select * from sales;
Now query the FIND_DEPEND view to view dependencies in the database. Limit the scope of the query to the PUBLIC schema, as shown in the following code:
select * from find_depend where refbyschemaname='public' order by name;
This query returns the following dependencies, showing that the SALES_VIEW view is also dropped by using the CASCADE option when dropping the SALES table:
tbloid | schemaname | name | viewoid | refbyschemaname | refbyname --------+------------+-------------+---------+-----------------+------------- 100241 | public | find_depend | 100241 | public | find_depend 100203 | public | sales | 100245 | public | sales_view 100245 | public | sales_view | 100245 | public | sales_view (3 rows)
Dropping a Table Using IF EXISTS
The following example either drops the FEEDBACK table if it exists, or does nothing and returns a message if it does not:
drop table if exists feedback;


| 2 Feb 1905 |
Alissa Zinovievna Rosenbaum born, St. Petersburg, Russia. |
| 1924 |
Graduates, University of Leningrad. |
| 26 Jan 1926 |
Leaves Russia for America. |
| 18 Feb 1926 |
Arrives in New York City. |
| Sep 1926 |
Movie extra for Cecil B. DeMille film King of Kings. |
| 15 Feb 1929 |
Marries actor Frank O'Conner. |
| 13 Mar 1931 |
Naturalized as an American citizen. |
| 31 Dec 1942 |
Finishes manuscript of The Fountainhead. |
| 6 May 1943 |
The Fountainhead published. |
| 1949 |
Film adaptation of The Fountainhead. |
| 1957 |
Atlas Shrugged -- 1,168 pages. |
| 6 Mar 1982 |
Ayn Rand dies in her New York City apartment. |


This is one in a series of guides discussing software tools and their use in Lever projects. Working through this guide will provide a basic understanding of git and GitHub as well as a start on the use of VSCODE with Lever.
git is a developer's tool that can be used to manage the source code for your projects. It provides a way to experiment with changes to the code and to track changes once they're finalized.
git is designed to be multi-user. It allows different developers to work on the same project at the same time without getting in each other's way. Developers can contribute fixes to the codebase in general or focus on maintaining different branches, or versions, of the code.
git is one of several competing tools known as Version Control Systems. This particular tool was created by Linus Torvalds, the original developer of Linux. To read more about Version Control Systems, click here.
git can be used as a stand-alone tool on one developer's PC or as a collaborative tool. In the latter case, a codebase lives on a server, which may be a private machine that belongs to a venture or a public git web service.
If you'd like simply to share your source code for others to use, it's easy to create a source tarball and link to it. However, if the goal is to open your project up to collaborative development, presently, git web services are one of the best approaches.
Typically, git web services are free, up to a point, but charge for extra features. There are several services of this type. The best one is generally considered to be GitHub. GitHub is located online at the following link:
Correct the following as necessary:
This guide outlines the setup of git under Windows and illustrates basic workflows for git both as a stand-alone tool and in conjunction with GitHub.
As a sample project, we'll use a VSCODE component written in Lever.
The focus is Windows as VSCODE is highly Windows-specific. Separate guides may be added for Linux Lever projects in the future.
If you work through this guide, you should be comfortable with git for Windows at the end and, additionally, you'll pick up a bit related to working with VSCODE and the Lever codebase.
Please work through the following guide first:
How to get started with vscode.
If you read through the getting started with vscode -guide You created a hello-world folder. Open that folder with the 'File' -menu. If someone has deleted that directory, it's okay. Just create a new directory and put something there. But open a directory anyway, it will become a git repository in this guide.
In the left tab you've got this diamond shaped symbol, when you press it tells you 'git' is not installed.
The next step is to install Git for Windows, if you don't already have it.
If you click at the 'git-scm.com' -link, it starts to download git. Let it finish and run the installer. Then step through until you hit a following dialog.
Earlier dialogs have lot of options, they seem to be right from the start, and it's okay for you to change them if you know something about what each means. One thing is that you probably want to keep the "Git Bash Here" and "Git GUI Here" installed. They are both very useful.
In this dialog you are best off by checking 'Checkout as-is, commit as-is' here.
There are lot of programming terms such as 'checkout' or 'commit' here. So, it may look a bit chaotic.
This part is optional.
The line-ending issue is historical. To read more about it, click here.
In short, many early computers fed text directly from the memory to a teletype printer head that printed characters to paper. CR is a control character that made the print head to switch to a new line.
Because the print head was not fast enough, it did not manage to finish the operation in time and you would often see the next letter get printed to a middle of page. To avoid this, text files ended up with CR+LF sequence, with the LF doing nothing. This gave the print head enough time to return.
Hardware drivers eventually ended up to abstract away the details, and computers were free to use a single character as newline. Unix adopted the LF as a newline, while Windows kept using CR+LF as a newline.
The problem here is that Git is very sensitive for line feed characters. If the line feed convention changes along the way, it renders the Git diff useless. There are some places where you still see CR+LF used, but they appear in protocols and such, not in text files. The standard we use with Lever files is to just use LF everywhere.
We recommend 'Checkout as-is' because this means you get a repository directory that is safe to move from a computer to an another without committing it through Git. You have an editor, that if you put like I proposed is configured to use LF everywhere. Also the VSCode doesn't force the file encoding so you shouldn't have problem with editing text files using any of the above settings.
Once you have a git installed, you can create a git repository in VSCode!
I'll pause here and suggest the following changes: Add step numbers to organize things a bit more. Possibly add step titles to the step numbers.
I assume that the flow is as follows: You install Git for Windows, the hello-world project is added to git, you create a repo on the GitHub side, and then you make changes and commit. Is it something like this? Make the flow clearer to the casual reader.
If Git Bash is part of this, should probably add a paragraph or two explaining more about what it is and linking to a Git Bash tutorial.
There are images further down that need more context. The casual reader will like to understand what is going on, not just execute steps exactly.
Now you have a git repository and the git tab is active. It's showing up the changes that haven't been committed to the repository.
Git created a directory for you that has a history. Every git directory has a history that is stored in '.git' -folder. It is possible to checkout a from any point in this history and see how the directory looked back then. For example, here's the directory tree of a first commit to lever repository. It looked like that in October 29, 2014!
This is very useful feature for managing your projects.
The chances are transferred into history in stagings, multiple files at once. Every stage gets a message that should tell what was done.
Lets make the first commit. There is very clear plus -sign that appears next to a file in that list. Press it to stage a file.
The staged changes appear into their separate list. We leave the main.lc.cb away because that's a binary file that Lever compiles from main.lc before it runs it.
To commit something you need a message, but this is the very first commit so we can give it a message 'initial commit'.
BOINK! Git hits you to the head! You lose 5 sanity points!!
To avoid this, open the GIT Bash to get this kind of very discomforting black screen you've probably seen in hacking movies. Type the commands such as in the screenshot, but replace 'cheery' with user name of your own, and the email address with your own. These lines tag and identify the code you wrote.
I'm not sure, but the name perhaps must be the same you use with your upcoming github account. You can change it later with this very same way.
Now you should be able to commit!

If you've run a program with lever, you got one right there named 'main.lc.cb'. To ignore all files with lever bytecode file extension, add the following line '*.lc.cb' to new file '.gitignore'
I also made '.vscodeignore', because I thought it would ignore files in vscode -view. Turns out I was wrong.
Prefer to describe what you do in the commit message. It is common to see very bad commit messages and it is understandable because naming can be hard. But you will get better every time you try. Eventually it will become your second nature to write meaningful commit messages.
When something becomes useless later on, you can delete it from the tree and stage a commit to delete it.
Notice that this does not delete a file from the history.  There are some gentler, but very much more challenging ways to remove files. Best way to avoid this is to not do that error in the first place.
If you can invalidate the information the file contains, it's usually better way than to change a git repository.
If the file isn't very dangerous, the best way is to let it stay in the history. It's the job of git to handle the history. Let it do its job.
So.. We gits have a hub these days. We call it Github!
The following sequences shows out how to create a public repository where you can push changes from your local repository.
There's a very little button in the upper right corner of the site...
...And it opens up like this. The best results are gained by names that tell something important about your work. For example 'nike' is a goddess of victory. A fine name for sports clothing. Do the same trick and you'll be walking along the titans.
Remember to keep the next page open.
So there's no much use of this if you can't push your changes from your repository to the github repository. To use the above lines you need to open a Git Bash to your repository.
If github is new SSH destination to you, you see this kind of message. Just type 'yes' as answer and press return.
BOINK! Github hits you to the head! Well no. Actually it just denies your access to the repository because it cannot know it is yours. You need to authenticate.
Public-key authentification.. Safer than any other authentification method as long as people do not snuff or see your private key. If it's not your personal computer that is safe from snoopys, remember to invalidate the key at github's end afterwards.
The program prints out fancy things such as a fingerprint and ASCII art. They aren't very interesting. Check out the path it points out. Open the whole directory in your VSCode.
The 'id_rsa' is a private key. People who have this key can identify as you.
The 'known_hosts' probably contain the github now because you said 'yes' to an important question. It's OK. Just good to know where those things go.
The 'id_rsa.pub' is your public key. Copy it from your file!
Go to https://github.com/settings/keys in your browser and press 'New SSH Key', paste your public key and name it something that identifies the computer you have. I put 'esa computer' there because I am on his computer. Notice the button 'Delete' - that lets you invalidate your key any time.
Next when you try the same thing as again, it lets you do it. Below you see the outcome.
After a while also your VSCode recognizes this. You can notice you will be able to 'Sync', 'Pull' and 'Push' from the menu aside the 'do a barrel roll!' -button.
I made a commit on the github website so I could pull. You see the '1' and a downarrow in the status bar aside the words 'master'.
Doing the pull changes the markings, like this.
So, is this worth all the effort? Might be the first thing you ask when you get accomodated to version control of any kind. I use it because it enables incredibly rapid collaboration and allows everyone to grab a development version and contribute.
I have no brightest idea how it could benefit you. But you would be able of writing guides such as this, or sample programs. Or then improve and document the existing sample programs and guides using git & github.
Signing in to github also enables you to submit issues to lever repository, allowing the community to react on what you feel you think needs work.
Also it's weird but knowing how to use git&github allows you to contribute to lots of things. For example there's this guy who wrote a kernel. Say you wanted to contribute to such projects somehow, maybe fix something there for yourself. You could press the 'fork' button to get a clone of this repository to github where you can commit your own changes. Then you could make a 'new pull request' to the original maintainer and he can decide whether to pull your changes or not.
If he doesn't like your changes and rejects them, you could keep your fork and still use it yourself, as long as you follow the license rules. It's even optional to keep it in sync with the mainline and update it from time to time, though you may want to stay updated for your sake if you fork a kernel.
If want to write closed source code, you could ignore github or then use their private repositories -feature that costs a little bit. Overall using git is still useful even if you didn't intend to put anything online.
There's lot ways to operate on git repositories using Git Bash. But they're out scope of what I should teach to you. This is here because I think it's something every programmer should know how to do.
The guide coming after this one will explain how to compile Lever on windows 10. It's something skilled programmers want to do, because Lever can miss a feature or two they want, even if that feature was otherwise trivial to implement.


Asynchronus JavaScript
From Callback Hell to Promises
Open chrome console to see code output
Code Example


Big data can be daunting! We use state-of-the-art exploratory data analysis tools to help you explore, summarise, visualize and find the patterns hidden in your data.
Do you have a complex data problem that urgently needs solving but you can't justify a full time data science hire?
We can take on your analytics projects and quickly refine the valuable insights buried deep in your data. We have years of experience in choosing the right model to fit the right data to answer the right question
Data fusion is the process of integrating multiple datasets into a single fused dataset. This enables them to be analysed together in a consistent way that is more useful than analysing the original datasets independently.
We have extensive experience in conducting large survey and media data fusions using the MRI, Simmons and Numeris establishment surveys to create powerful media planning tools.
We are experts at implementing:
Unconstrained Fusions: Where an, often smaller but more detailed, dataset is calibrated to another, possibly from a trusted establishment study
Constrained Fusion: Where two well-calibrated datasets are combined by sharing the weights from one to the other. This leaves both datasets essentially unchanged
Having a model that works is only the first step towards having a true data product that you can use in your apps or sites.
You need a solution flexible enough for your analysts to be able to tweak and update the model but robust enough to not break under the pressure of production use at scale.
We will advise you on the best way to set up data science workflows in production that works for your business, whether it be R, Python or big data technology like Spark or Hadoop. Then we can work with your data engineers to get your models into production.
Big Data will continue to have a fundamental impact on your business over the next few years. Without a detailed data science strategy with a tangiable end goal, you could waste money or worse, end up investing in a solution that is looking for a problem
We have experience working with businesses and teams in marketing, online media, informatics, acedemia and healthcare. We will help you design and implement a data science strategy and to build effective, data driven, teams. Investing time and effort upfront will prepare you to choose technology and staff that truely support the current and future needs of your business.
We have years of experience in data science, R and Python programming, including several years in academia. Whether you need one-on-one training for a specific problem or you want to upskill a whole team, we can put together a training package that is good for you.
We can also provide a mentorship programme involving regular training and technical advice over the phone or Skype.
Contact us to discuss your needs.


Bottle is a fast, simple and lightweight WSGI micro web-framework for Python. It is distributed as a single file module and has no dependencies other than the Python Standard Library.
Example: “Hello World” in a bottle
from bottle import route, run, template
@route('/hello/<name>')
def index(name):
return template('<b>Hello {{name}}</b>!', name=name)
run(host='localhost', port=8080)
Run this script or paste it into a Python console, then point your browser to http://localhost:8080/hello/world. That’s it.
Download and Install
Install the latest stable release via PyPI (easy_install -U bottle) or download bottle.py (unstable) into your project directory. There are no hard [1] dependencies other than the Python standard library. Bottle runs with Python 2.5+ and 3.x.
Start here if you want to learn how to use the bottle framework for web development. If you have any questions not answered here, feel free to ask the mailing list.
A collection of articles, guides and HOWTOs.
These chapters are intended for developers interested in the bottle development and release workflow.
Code and documentation are available according to the MIT License:
Copyright (c) 2012, Marcel Hellkamp.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
 IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
The Bottle logo however is NOT covered by that license. It is allowed to use the logo as a link to the bottle homepage or in direct context with the unmodified library. In all other cases please ask first.
Footnotes
| [1] | Usage of the template or server adapter classes of course requires the corresponding template or server modules. |


Node's default require extensions as a separate module
Handy for require extension authors that want reliable access to the default extension implementations.
By the time your extension is loaded, the default extension may have already been replaced. This provides extensions functionally identical to the default ones, which you know you can access reliably, no matter what extensions have been installed previously.
$ npm install --save default-require-extensions
const js = require('default-require-extensions/js');
const json = require('default-require-extensions/json');
require.extensions['.js'] = js;
require.extensions['.js'] = json;
*Note: * You would never actually do the above. Use these in your custom require extensions instead.
MIT © Node.js contributors, James Talmage