61

Exceptions, especially checked ones, can severely interrupt the flow of program logic when the FP idiom is used in Java 8. Here is an arbitrary example:

String s1 = "oeu", s2 = "2";
Stream.of(s1, s2).forEach(s -> 
    System.out.println(Optional.of(s).map(Integer::parseInt).get()));

The above code breaks when there's an exception for an unparseable string. But say I just want to replace that with a default value, much like I can with Optional:

Stream.of(s1, s2).forEach(s -> 
   System.out.println(Optional.of(s)
                              .map(Integer::parseInt)
                              .orElse(-1)));

Of course, this still fails because Optional only handles nulls. I would like something as follows:

Stream.of(s1, s2).forEach(s ->
    System.out.println(
        Exceptional.of(s)
                   .map(Integer::parseInt)
                   .handle(NumberFormatException.class, swallow())
                   .orElse(-1)));

Note: this is a self-answered question.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • For the `orElse` part, instead of returning `-1`, is there a way to just omit the element. So that the resulting stream would have fewer elements if there are exceptional elements. – hrzafer Feb 22 '18 at 22:52
  • In the provided example, Exceptional enters the picture in the terminal operation, where the stream's contents are already settled. You can write a different expression that involves a `flatMap` stage, and you can add a `.stream()` method to Exceptional: `Stream stream() { return isPresent() ? Stream.of(value) : Stream.empty(); }` Then you can say `stream.flatMap(Exceptional::stream)` – Marko Topolnik Feb 23 '18 at 07:27

4 Answers4

57

Presented below is the full code of the Exceptional class. It has a quite large API which is a pure extension of the Optional API so it can be a drop-in replacement for it in any existing code—except that it isn't a subtype of the final Optional class. The class can be seen as being in the same relationship with the Try monad as Optional is with the Maybe monad: it draws inspiration from it, but is adapted to the Java idiom (such as actually throwing exceptions, even from non-terminal operations).

These are some key guidelines followed by the class:

  • as opposed to the monadic approach, doesn't ignore Java's exception mechanism;

  • instead it relieves the impedance mismatch between exceptions and higher-order functions;

  • exception handling not statically typesafe (due to sneaky throwing), but always safe at runtime (never swallows an exception except on explicit request).

The class tries to cover all the typical ways to handle an exception:

  • recover with some handling code which provides a substitute value;
  • flatRecover which, analogous to flatMap, allows to return a new Exceptional instance which will be unwrapped and the state of the current instance suitably updated;
  • propagate an exception, throwing it from the Exceptional expression and making the propagate call declare this exception type;
  • propagate it after wrapping into another exception (translate it);
  • handle it, resulting in an empty Exceptional;
  • as a special case of handling, swallow it with an empty handler block.

The propagate approach allows one to selectively pick which checked exceptions he wants to expose from his code. Exceptions which remain unhandled at the time a terminal operation is called (like get) will be sneakily thrown without declaration. This is often considered as an advanced and dangerous approach, but is nevertheless often employed as a way to somewhat alleviate the nuisance of checked exceptions in combination with lambda shapes which do not declare them. The Exceptional class hopes to offer a cleaner and more selective alternative to sneaky throw.


/*
 * Copyright (c) 2015, Marko Topolnik. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public final class Exceptional<T>
{
  private final T value;
  private final Throwable exception;

  private Exceptional(T value, Throwable exc) {
    this.value = value;
    this.exception = exc;
  }

  public static <T> Exceptional<T> empty() {
    return new Exceptional<>(null, null);
  }

  public static <T> Exceptional<T> ofNullable(T value) {
    return value != null ? of(value) : empty();
  }

  public static <T> Exceptional<T> of(T value) {
    return new Exceptional<>(Objects.requireNonNull(value), null);
  }

  public static <T> Exceptional<T> ofNullableException(Throwable exception) {
    return exception != null? new Exceptional<>(null, exception) : empty();
  }

  public static <T> Exceptional<T> ofException(Throwable exception) {
    return new Exceptional<>(null, Objects.requireNonNull(exception));
  }

  public static <T> Exceptional<T> from(TrySupplier<T> supplier) {
    try {
      return ofNullable(supplier.tryGet());
    } catch (Throwable t) {
      return new Exceptional<>(null, t);
    }
  }

  public static Exceptional<Void> fromVoid(TryRunnable task) {
    try {
      task.run();
      return new Exceptional<>(null, null);
    } catch (Throwable t) {
      return new Exceptional<>(null, t);
    }
  }

  public static <E extends Throwable> Consumer<? super E> swallow() {
    return e -> {};
  }

  public T get() {
    if (value != null) return value;
    if (exception != null) sneakyThrow(exception);
    throw new NoSuchElementException("No value present");
  }

  public T orElse(T other) {
    if (value != null) return value;
    if (exception != null) sneakyThrow(exception);
    return other;
  }

  public T orElseGet(Supplier<? extends T> other) {
    if (value != null) return value;
    if (exception != null) sneakyThrow(exception);
    return other.get();
  }

  public Stream<T> stream() { 
      return value == null ? Stream.empty() : Stream.of(value); 
  }

  public<U> Exceptional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (value == null) return new Exceptional<>(null, exception);
    final U u;
    try {
      u = mapper.apply(value);
    } catch (Throwable exc) {
      return new Exceptional<>(null, exc);
    }
    return ofNullable(u);
  }

  public<U> Exceptional<U> flatMap(Function<? super T, Exceptional<U>> mapper) {
    Objects.requireNonNull(mapper);
    return value != null ? Objects.requireNonNull(mapper.apply(value)) : empty();
  }

  public Exceptional<T> filter(Predicate<? super T> predicate) {
    Objects.requireNonNull(predicate);
    if (value == null) return this;
    final boolean b;
    try {
      b = predicate.test(value);
    } catch (Throwable t) {
      return ofException(t);
    }
    return b ? this : empty();
  }

  public <X extends Throwable> Exceptional<T> recover(
      Class<? extends X> excType, Function<? super X, T> mapper)
  {
    Objects.requireNonNull(mapper);
    return excType.isInstance(exception) ? ofNullable(mapper.apply(excType.cast(exception))) : this;
  }

  public <X extends Throwable> Exceptional<T> recover(
      Iterable<Class<? extends X>> excTypes, Function<? super X, T> mapper)
  {
    Objects.requireNonNull(mapper);
    for (Class<? extends X> excType : excTypes)
      if (excType.isInstance(exception))
        return ofNullable(mapper.apply(excType.cast(exception)));
    return this;
  }

  public <X extends Throwable> Exceptional<T> flatRecover(
      Class<? extends X> excType, Function<? super X, Exceptional<T>> mapper)
  {
    Objects.requireNonNull(mapper);
    return excType.isInstance(exception) ? Objects.requireNonNull(mapper.apply(excType.cast(exception))) : this;
  }

  public <X extends Throwable> Exceptional<T> flatRecover(
      Iterable<Class<? extends X>> excTypes, Function<? super X, Exceptional<T>> mapper)
  {
    Objects.requireNonNull(mapper);
    for (Class<? extends X> c : excTypes)
      if (c.isInstance(exception))
        return Objects.requireNonNull(mapper.apply(c.cast(exception)));
    return this;
  }

  public <E extends Throwable> Exceptional<T> propagate(Class<E> excType) throws E {
    if (excType.isInstance(exception))
      throw excType.cast(exception);
    return this;
  }

  public <E extends Throwable> Exceptional<T> propagate(Iterable<Class<? extends E>> excTypes) throws E {
    for (Class<? extends E> excType : excTypes)
      if (excType.isInstance(exception))
        throw excType.cast(exception);
    return this;
  }

  public <E extends Throwable, F extends Throwable> Exceptional<T> propagate(
      Class<E> excType, Function<? super E, ? extends F> translator)
  throws F
  {
    if (excType.isInstance(exception))
      throw translator.apply(excType.cast(exception));
    return this;
  }

  public <E extends Throwable, F extends Throwable> Exceptional<T> propagate(
      Iterable<Class<E>> excTypes, Function<? super E, ? extends F> translator)
  throws F
  {
    for (Class<? extends E> excType : excTypes)
      if (excType.isInstance(exception))
        throw translator.apply(excType.cast(exception));
    return this;
  }

  public <E extends Throwable> Exceptional<T> handle(Class<E> excType, Consumer<? super E> action) {
    if (excType.isInstance(exception)) {
      action.accept(excType.cast(exception));
      return empty();
    }
    return this;
  }

  public <E extends Throwable> Exceptional<T> handle(Iterable<Class<E>> excTypes, Consumer<? super E> action) {
    for (Class<? extends E> excType : excTypes)
      if (excType.isInstance(exception)) {
        action.accept(excType.cast(exception));
        return empty();
      }
    return this;
  }

  public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
    if (value != null) return value;
    if (exception != null) sneakyThrow(exception);
    throw exceptionSupplier.get();
  }

  public boolean isPresent() {
    return value != null;
  }

  public void ifPresent(Consumer<? super T> consumer) {
    if (value != null)
      consumer.accept(value);
    if (exception != null) sneakyThrow(exception);
  }

  public boolean isException() {
    return exception != null;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    return obj instanceof Exceptional && Objects.equals(value, ((Exceptional)obj).value);
  }

  @Override
  public int hashCode() {
    return Objects.hashCode(value);
  }

  @SuppressWarnings("unchecked")
  private static <T extends Throwable> void sneakyThrow(Throwable t) throws T {
    throw (T) t;
  }
}

@FunctionalInterface
public interface TrySupplier<T> {
  T tryGet() throws Throwable;
}

@FunctionalInterface
public interface TryRunnable {
  void run() throws Throwable;
}
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • 3
    Don't forget to update your answer if you decide to put this class in some repository :) – Pshemo Jul 07 '15 at 14:40
  • 4
    @the8472 Stackoverflow => [Creative Commons](http://creativecommons.org/licenses/by-sa/3.0/) – assylias Jul 07 '15 at 15:11
  • Nice one! Would it make sense to have a `handle(Consumer super E> action, Class... excType)` to allow `handle(swallow(), Exception1.class, Exception2.class)` (although the order of arguments is less intuitive)... – assylias Jul 07 '15 at 15:17
  • 2
    Another example of a 'Try' monad for java by Mario Fusco can be found here: https://github.com/mariofusco/javaz/blob/master/src/main/java/org/javaz/Try.java. – Jeff Jul 07 '15 at 15:19
  • 2
    @assylias I thought long about it, but decided it's not worth the loss of intuitiveness, given the availability of `asList(Exception1.class, Exception2.class)`. – Marko Topolnik Jul 07 '15 at 15:23
  • @Jeff Note that `Exceptional` is *not* a `Try` monad, just like `Optional` is not a `Maybe` monad. It takes some pragmatic, non-pure FP choices. – Marko Topolnik Jul 07 '15 at 15:30
  • 1
    Note that Java 8’s improved type inference even makes the sneaky throw hack more pleasant ;^). I.e. you don’t need the type witness, but can just write `Exceptional.sneakyThrow0(t);` or, even simpler, `sneakyThrow0(t);` and the compiler will infer an unchecked exception for you… – Holger Jul 07 '15 at 16:43
  • @Holger What a nice addition to this subversion of the type system :) But I must say I'm surprised: by what rules does the compiler infer an unchecked exception? I pass a `Throwable` to `sneakyThrow0`, which then throws it. Does it infer an unchecked exception just because the method doesn't declare, using the liberties of the unchecked cast? – Marko Topolnik Jul 07 '15 at 16:52
  • 3
    @MarkoTopolnik When the compiler is trying to infer the type of `X extends Throwable` it will [prefer an unchecked exception](http://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html#jls-18.1.3): `it directs resolution to optimize the instantiation of α so that, if possible, it is not a checked exception type` – Jeffrey Jul 07 '15 at 16:59
  • 3
    There are proposals to add a similar type to C++, under the name `expected`. As in `expected` is expected to be an `int`, but if not the reason is `exception`. See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4015.pdf -- it is similar, but less tied to exceptions. – Yakk - Adam Nevraumont Jul 07 '15 at 17:06
  • 1
    @Holger Actually, the whole inner method becomes redundant: `@SuppressWarnings("unchecked") static void sneakyThrow(Throwable t) throws T { throw (T) t; }` Now, if *that* isn't weird code... – Marko Topolnik Jul 07 '15 at 17:32
  • @Yakk I tried to read that spec doc, but it isn't written very clearly. From your description it looks more like the `Either` monad than the class presented here, which is decidedly not a monad. – Marko Topolnik Jul 07 '15 at 17:43
  • 1
    @MarkoTopolnik sort of. It is an extension of `optional`/`Maybe` pseudo-monad like yours is, it just replaces the `nullopt` possibility with the exception (the excuse for it not being the thing it is expected to be). `Either` monad is not, to my knowledge, biased towards one of the two options. And yes, it is hard to read, as it is written presuming you are fluent in other C++1z proposals, and rather than showing the design is mainly about discussing the design decisions. It is probably less tied to exceptions than your design is. – Yakk - Adam Nevraumont Jul 07 '15 at 18:08
  • 2
    @yakk It's actually more like the `Try` monad (which is left-biased), but I wanted to point out what I see as the main distinction between my class and the monads: `expected` *encapsulates* failure as a value whereas my class just allows a nicer idiom to imperatively handle exceptions. Just like `Optional` is a tool to replace the `if` statement with an expression (and avoid some boilerplate null-checking), so is `Exceptional` a tool to do the same with the `try`-`catch` statement. – Marko Topolnik Jul 07 '15 at 18:12
  • I don't see the big difference: your `map` has a `catch` that returns an exception encapsulated? Once the exception has been encapsulated, you just have methods that let you get the exception out again, or the value, that are chainable? – Yakk - Adam Nevraumont Jul 07 '15 at 19:27
  • 1
    In a belated response to Yakk... the main thrust of my design is in the `propagate` method, which actually *throws* the exception. A further choice was to always throw any remaining exception upon a terminal operation. This is in stark opposition to the monadic approach, whereas the C++ proposal is in line with it. – Marko Topolnik Jul 08 '15 at 07:36
  • 1
    I would like to add one more comment about the monadic nature of `Exceptional`: yes, it can be shown to satisfy the three monadic laws, just like any other class which happens to define `flatMap` and has a suitable constructor. If we extended `ArrayList` with that method, it would "become a monad", too. But there's much more to monads than the formality: it's about how they are actually used and composed with the rest of the system. This is where the intention behind `Exceptional` starkly diverges from the monadic philosophy, as explained earlier. – Marko Topolnik Jul 09 '15 at 07:31
  • 1
    This would benefit from a `stream` method so you can flatMap a single result (or no result): `public Stream stream() { return value == null ? Stream.empty() : Stream.of(value); }` – john16384 Jun 10 '18 at 11:45
  • @john16384 Method added. – Marko Topolnik Jun 10 '18 at 13:05
10

What if every functional interface provided by java.util.function was allowed to throw an exception?

public interface ThrowingSupplier<R, X extends Throwable> {
    public R get() throws X;
}

We could use some default methods to provide the behavior you want.

  • You could fallback to some default value or action
  • Or you could try to perform another action which may throw an exception

I've written a library which redefines most of the interfaces in java.util.function this way. I even provide a ThrowingStream which let's you use these new interfaces with the same API as a regular Stream.

@FunctionalInterface
public interface ThrowingSupplier<R, X extends Throwable> {
    public R get() throws X;

    default public Supplier<R> fallbackTo(Supplier<? extends R> supplier) {
        ThrowingSupplier<R, Nothing> t = supplier::get;
        return orTry(t)::get;
    }

    default public <Y extends Throwable> ThrowingSupplier<R, Y> orTry(
            ThrowingSupplier<? extends R, ? extends Y> supplier) {
        Objects.requireNonNull(supplier, "supplier");
        return () -> {
            try {
                return get();
            } catch (Throwable x) {
                try {
                    return supplier.get();
                } catch (Throwable y) {
                    y.addSuppressed(x);
                    throw y;
                }
            }
        };
    }
}

(Nothing is a RuntimeException that can never be thrown.)


Your original example would become

ThrowingFunction<String, Integer, NumberFormatException> parse = Integer::parseInt;
Function<String, Optional<Integer>> safeParse = parse.fallbackTo(s -> null)
    .andThen(Optional::ofNullable);
Stream.of(s1, s2)
    .map(safeParse)
    .map(i -> i.orElse(-1))
    .forEach(System.out::println);
Jeffrey
  • 44,417
  • 8
  • 90
  • 141
6

Here's some discussions I had previously on this topic.

I made an interface Result<T> along the reasonings. A Result<T> is either a success with a value of type T, or a failure with an Exception. It's a subtype of Async<T>, as an immediately completed async action, but that is not important here.

To create a result -

Result.success( value )
Result.failure( exception )
Result.call( callable )

Result can then be transformed in various ways - transform, map, then, peek, catch_, finally_ etc. For example

Async<Integer> rInt = Result.success( s )
      .map( Integer::parseInt )
      .peek( System.out::println )
      .catch_( NumberFormatException.class, ex->42 ) // default
      .catch_( Exception.class, ex-> { ex.printStacktrace(); throw ex; } )
      .finally_( ()->{...} )

Unfortunately the API is focusing on Async, so some methods return Async. Some of them can be overridden by Result to return Result; but some cannot, e.g. then() (which is flatmap). However, if interested, it's easy to extract a standalone Result API that has nothing to do with Async.

ZhongYu
  • 19,446
  • 5
  • 33
  • 61
  • This seems pretty similar to [`CompletableFuture`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html). – Jeffrey Jul 07 '15 at 20:25
  • @Jeffrey - You are right on target. I was hoping that `CompletionStage` would be the interface we desperately needed for async programming in Java. Such an interface should be a standard one from JDK: nobody wants to create their proprietary ones. Unfortunately, `CompletionStage` is not suitable to play that role. I was forced to (I did not want to!) create my own for my async http lib. – ZhongYu Jul 07 '15 at 20:35
  • 1
    This looks very well aligned with my goals. One thing that would definitely not work, though, is `finally_()` because any previous step may have already thrown an exception. To make this work the whole implementation would have to be lazy, just remembering the steps you asked for and then replaying them on a terminal operation. I'm also quite sure that sneaky throwing will never find its way into an API like this one :) – Marko Topolnik Jul 07 '15 at 20:48
  • @MarkoTopolnik - `finally_()` works, because exceptions in previous lambdas won't leak; `map(v->{ throw ex; })` simply transforms the success result to a failure result. – ZhongYu Jul 07 '15 at 20:55
  • @MarkoTopolnik - while async transformations must be lazy by nature, a synchronous only util like Result can be eager; every transformation is done immediately when the method is called. – ZhongYu Jul 07 '15 at 20:56
  • 1
    Ah, OK. Then it may not be the same idea as mine, which is to actually throw the exceptions (more precisely, to have both choices in the API). – Marko Topolnik Jul 07 '15 at 20:57
  • @MarkoTopolnik - it's an abstraction for "return T or throw Exception"; it can be de-abstracted by [getOrThrow()](http://bayou.io/release/0.9/javadoc/bayou/util/Result.html#getOrThrow--) – ZhongYu Jul 07 '15 at 20:58
  • 1
    One of my key ideas is the selective declaration of checked exceptions---so I need more than a blanket `getOrThrow`. I need to throw with a type filter applied. – Marko Topolnik Jul 07 '15 at 20:59
  • @MarkoTopolnik - that is quite unconventional, mixing two different programming styles. can you provide a use case for `propagate()` in the middle of transformation chain? – ZhongYu Jul 07 '15 at 21:08
  • 1
    My main use case here is using `Exceptional` internally inside a method, or inside a lambda body. You call a method, get a bunch of checked exceptions. You want to propagate an `IOException` as a checked one, but a bunch of reflection exceptions you just want to treat as failures. – Marko Topolnik Jul 07 '15 at 21:12
  • @MarkoTopolnik - that can be done at the last step of the chain, right? not necessary in the middle of the chain. – ZhongYu Jul 07 '15 at 21:13
  • 1
    But I don't want to turn my expression into a `try` statement to do it. This is much more convenient. If Java didn't have the statement/expression dichotomy, this would probably not be as big a deal. – Marko Topolnik Jul 07 '15 at 21:14
  • @MarkoTopolnik - yes, but I mean I can add a method for `getOrThrow(IOException.class)` for your requirement, right? But it has to be a terminal method in my API. – ZhongYu Jul 07 '15 at 21:16
  • 1
    I see... but I don't think it's as general. I may want to `recover` from an exception, then `map` to something else, getting a new failure, and only the latter case I want to `propagate`. `Exceptional` can flip-flop from success to failure and back any number of times. – Marko Topolnik Jul 07 '15 at 21:21
  • @MarkoTopolnik - to simulate short-circuit return/throw, e.g. `if(condition) return/throw ... ; rest-of-code`, we can use flatmap, e.g. `.flatmap( (v,ex)->{ if(condition) return Success/Failure; rest-of-code } )` – ZhongYu Jul 07 '15 at 21:37
  • @bayou.io Out of curiosity, why do you feel that `CompletionStage` isn't suitable? What would make it more suitable? – Jeffrey Jul 07 '15 at 21:41
  • @MarkoTopolnik - `rest-of-code` is now inside flatmap, in a deeper nesting, instead of as a follow-up clause after flatmap. This is indeed ugly. Maybe the API needs to add short-circuit methods, e.g. `shortcut(condition, result)` - if condition is met, everything after the shortcut call are ignored. – ZhongYu Jul 07 '15 at 21:43
  • 1
    @Jeffrey - I got the feeling, from Doug Lea's discussions on the concurrency-interest mailing list, that he is more interested in provide a robust functionality suite, that others can build on top to provide prettier APIs; he himself is not interested in providing a pretty API. I think he knows all those various choices of pretty APIs, and he doesn't want to get involved. – ZhongYu Jul 07 '15 at 21:47
  • 2
    @Jeffrey - more specifically, what I don't like about it - cancellation mechanism; mutability(!); no checked exceptions in lambda body; bloated APIs, long class/method names; too many methods instead of fewer composable methods; lack of some convenience methods. – ZhongYu Jul 07 '15 at 21:51
  • more thinking on short-circuit: a better analogy is `break` statement, which can skip the rest of the code in a block. if we are honest, `break` is just `goto`, but forward only. so we could design an API like `gotoIf("lable", condition, result).map(...)...transform(...).label("label")`. If `condition` holds, actions between `gotoIf` and `label` are skipped. It is very important though to set a matching label, otherwise we cannot transfer this Async to someone else who wants more transformations. – ZhongYu Jul 07 '15 at 23:51
  • hmm... not much better, visually, than nesting it in flatmap. forget it. – ZhongYu Jul 08 '15 at 00:12
  • 1
    From my current understanding, you either have short circuiting or `finally`. I'm happier to lose `finally`, but I think I'm considering a quite different use case than the async completion stage, where it may be more important. – Marko Topolnik Jul 08 '15 at 05:06
5

There's a third-party library called better-java-monads. It has the Try monad which provides the necessary functions. It also has TryMapFunction and TrySupplier functional interfaces to use the Try monad with checked exceptions.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
  • 3
    I actually designed my class as a response to what I saw in `Either` and `Try`. They just regurgitate the same well-known theme of monads which I don't find particularly practical outside Haskell. They strictly adhere to the religion of pure FP, statelessness and immutability. Almost everything is expressed as a type transformation, which suits a powerful type system like Haskell's much better than Java. Also, they don't mesh well with the rest of the standard library and existing code; for example by completely sidestepping the exception system. – Marko Topolnik Jul 07 '15 at 17:52