All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.revenj.ChangeNotification Maven / Gradle / Ivy

The newest version!
package org.revenj;

import org.revenj.extensibility.Container;
import org.revenj.extensibility.InstanceScope;
import org.revenj.patterns.DataChangeNotification;
import rx.Observable;
import rx.Subscription;
import rx.subjects.PublishSubject;

import java.io.Closeable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;

final class ChangeNotification implements Closeable {

	private final Subscription subscription;

	private ChangeNotification(Class manifest, DataChangeNotification notifications) {
		PublishSubject> subject = PublishSubject.create();
		subscription = notifications.track(manifest).subscribe(subject::onNext);
		Observable> source = subject.asObservable();

		bulkChanges = source.map(it -> it.result);
		lazyChanges =
				source.flatMapIterable(it -> {
					try {
						List> callables = new ArrayList<>(it.uris.length);
						for (int i = 0; i < it.uris.length; i++) {
							int ind = i;
							callables.add(() -> it.result.call().get(ind));
						}
						return callables;
					} catch (Exception e) {
						throw new RuntimeException(e);
					}
				});
		eagerChanges = source.flatMapIterable(it -> {
			try {
				return it.result.call();
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		});
	}

	private final Observable eagerChanges;
	private final Observable> lazyChanges;
	private final Observable>> bulkChanges;

	public static void registerContainer(Container container, final DataChangeNotification notification) {
		container.registerGenerics(
				rx.Observable.class,
				(locator, arguments) ->
				{
					if (arguments.length == 1) {
						Type arg = arguments[0];
						if (arg instanceof Class) {
							ChangeNotification cn = new ChangeNotification((Class) arg, notification);
							return cn.eagerChanges;
						} else if (arg instanceof ParameterizedType && ((ParameterizedType) arg).getRawType() == Callable.class) {
							Type[] genericArguments = ((ParameterizedType) arg).getActualTypeArguments();
							if (genericArguments.length == 1) {
								Type first = genericArguments[0];
								if (first instanceof Class) {
									ChangeNotification cn = new ChangeNotification((Class) first, notification);
									return cn.lazyChanges;
								}
								if (first instanceof ParameterizedType) {
									ParameterizedType npt = (ParameterizedType) first;
									if (npt.getActualTypeArguments().length == 1
											&& npt.getRawType() instanceof Class
											&& npt.getActualTypeArguments()[0] instanceof Class
											&& Collection.class.isAssignableFrom((Class) npt.getRawType())) {
										ChangeNotification cn = new ChangeNotification((Class) npt.getActualTypeArguments()[0], notification);
										return cn.bulkChanges;
									}
								}
							}
						}
					}
					throw new RuntimeException("Invalid arguments for Observable. Supported arguments: Observable>>, Observable and Observable>");
				},
				InstanceScope.TRANSIENT
		);
	}

	public void close() {
		subscription.unsubscribe();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy