aries-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From csie...@apache.org
Subject svn commit: r1797036 - in /aries/trunk/component-dsl: component-dsl/ component-dsl/src/main/java/org/apache/aries/functional/ component-dsl/src/main/java/org/apache/aries/osgi/functional/ component-dsl/src/main/java/org/apache/aries/osgi/functional/int...
Date Wed, 31 May 2017 13:23:49 GMT
Author: csierra
Date: Wed May 31 13:23:49 2017
New Revision: 1797036

URL: http://svn.apache.org/viewvc?rev=1797036&view=rev
Log:
First attempt to implement Applicative

Added:
    aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/
    aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function1.java
    aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function2.java
    aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function3.java
    aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function4.java
    aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function5.java
    aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function6.java
Modified:
    aries/trunk/component-dsl/component-dsl/bnd.bnd
    aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/OSGi.java
    aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/JustOSGiImpl.java
    aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/OSGiImpl.java
    aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/Tuple.java
    aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/osgi/functional/test/ComponentTest.java
    aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/osgi/functional/test/DSLTest.java

Modified: aries/trunk/component-dsl/component-dsl/bnd.bnd
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/bnd.bnd?rev=1797036&r1=1797035&r2=1797036&view=diff
==============================================================================
--- aries/trunk/component-dsl/component-dsl/bnd.bnd (original)
+++ aries/trunk/component-dsl/component-dsl/bnd.bnd Wed May 31 13:23:49 2017
@@ -1 +1,3 @@
-Export-Package: org.apache.aries.osgi.functional
\ No newline at end of file
+Export-Package:\
+	org.apache.aries.functional,\
+	org.apache.aries.osgi.functional
\ No newline at end of file

Added: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function1.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function1.java?rev=1797036&view=auto
==============================================================================
--- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function1.java
(added)
+++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function1.java
Wed May 31 13:23:49 2017
@@ -0,0 +1,16 @@
+package org.apache.aries.functional;
+
+import java.util.function.Function;
+
+/**
+* @generated
+*/
+@FunctionalInterface
+public interface Function1<A,RESULT> {
+    
+    public RESULT apply(A a);
+    
+    default public Function<A,RESULT> curried() {
+        return a -> apply(a);
+    }
+}

Added: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function2.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function2.java?rev=1797036&view=auto
==============================================================================
--- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function2.java
(added)
+++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function2.java
Wed May 31 13:23:49 2017
@@ -0,0 +1,16 @@
+package org.apache.aries.functional;
+
+import java.util.function.Function;
+
+/**
+* @generated
+*/
+@FunctionalInterface
+public interface Function2<A,B,RESULT> {
+    
+    public RESULT apply(A a,B b);
+    
+    default public Function<A,Function<B,RESULT>> curried() {
+        return a -> b -> apply(a,b);
+    }
+}

Added: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function3.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function3.java?rev=1797036&view=auto
==============================================================================
--- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function3.java
(added)
+++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function3.java
Wed May 31 13:23:49 2017
@@ -0,0 +1,16 @@
+package org.apache.aries.functional;
+
+import java.util.function.Function;
+
+/**
+* @generated
+*/
+@FunctionalInterface
+public interface Function3<A,B,C,RESULT> {
+    
+    public RESULT apply(A a,B b,C c);
+    
+    default public Function<A,Function<B,Function<C,RESULT>>> curried()
{
+        return a -> b -> c -> apply(a,b,c);
+    }
+}

Added: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function4.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function4.java?rev=1797036&view=auto
==============================================================================
--- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function4.java
(added)
+++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function4.java
Wed May 31 13:23:49 2017
@@ -0,0 +1,16 @@
+package org.apache.aries.functional;
+
+import java.util.function.Function;
+
+/**
+* @generated
+*/
+@FunctionalInterface
+public interface Function4<A,B,C,D,RESULT> {
+    
+    public RESULT apply(A a,B b,C c,D d);
+    
+    default public Function<A,Function<B,Function<C,Function<D,RESULT>>>>
curried() {
+        return a -> b -> c -> d -> apply(a,b,c,d);
+    }
+}

Added: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function5.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function5.java?rev=1797036&view=auto
==============================================================================
--- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function5.java
(added)
+++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function5.java
Wed May 31 13:23:49 2017
@@ -0,0 +1,16 @@
+package org.apache.aries.functional;
+
+import java.util.function.Function;
+
+/**
+* @generated
+*/
+@FunctionalInterface
+public interface Function5<A,B,C,D,E,RESULT> {
+    
+    public RESULT apply(A a,B b,C c,D d,E e);
+    
+    default public Function<A,Function<B,Function<C,Function<D,Function<E,RESULT>>>>>
curried() {
+        return a -> b -> c -> d -> e -> apply(a,b,c,d,e);
+    }
+}

Added: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function6.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function6.java?rev=1797036&view=auto
==============================================================================
--- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function6.java
(added)
+++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/functional/Function6.java
Wed May 31 13:23:49 2017
@@ -0,0 +1,16 @@
+package org.apache.aries.functional;
+
+import java.util.function.Function;
+
+/**
+* @generated
+*/
+@FunctionalInterface
+public interface Function6<A,B,C,D,E,F,RESULT> {
+    
+    public RESULT apply(A a,B b,C c,D d,E e,F f);
+    
+    default public Function<A,Function<B,Function<C,Function<D,Function<E,Function<F,RESULT>>>>>>
curried() {
+        return a -> b -> c -> d -> e -> f -> apply(a,b,c,d,e,f);
+    }
+}

Modified: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/OSGi.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/OSGi.java?rev=1797036&r1=1797035&r2=1797036&view=diff
==============================================================================
--- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/OSGi.java
(original)
+++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/OSGi.java
Wed May 31 13:23:49 2017
@@ -18,6 +18,11 @@
 
 package org.apache.aries.osgi.functional;
 
+import org.apache.aries.functional.Function2;
+import org.apache.aries.functional.Function3;
+import org.apache.aries.functional.Function4;
+import org.apache.aries.functional.Function5;
+import org.apache.aries.functional.Function6;
 import org.apache.aries.osgi.functional.internal.BundleContextOSGiImpl;
 import org.apache.aries.osgi.functional.internal.BundleOSGi;
 import org.apache.aries.osgi.functional.internal.ChangeContextOSGiImpl;
@@ -36,6 +41,7 @@ import org.osgi.framework.ServiceObjects
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 
+import java.util.ArrayList;
 import java.util.Dictionary;
 import java.util.Map;
 import java.util.function.Consumer;
@@ -164,4 +170,28 @@ public interface OSGi<T> extends OSGiRun
 
 	}
 
+	public default <S> OSGi<S> applyTo(OSGi<Function<T, S>> fun) {
+		return fun.flatMap(this::map);
+	}
+
+	public static <A, B, C> OSGi<C> apply(Function2<A, B, C> fun, OSGi<A>
a, OSGi<B> b) {
+		return b.applyTo(a.applyTo(just(fun.curried())));
+	}
+
+	public static <A, B, C, D> OSGi<D> apply(Function3<A, B, C, D> fun, OSGi<A>
a, OSGi<B> b, OSGi<C> c) {
+		return c.applyTo(OSGi.apply((A aa, B bb) -> fun.curried().apply(aa).apply(bb), a, b));
+	}
+
+	public static <A, B, C, D, E> OSGi<E> apply(Function4<A, B, C, D, E> fun,
OSGi<A> a, OSGi<B> b, OSGi<C> c, OSGi<D> d) {
+		return d.applyTo(OSGi.apply((A aa, B bb, C cc) -> fun.curried().apply(aa).apply(bb).apply(cc),
a, b, c));
+	}
+
+	public static <A, B, C, D, E, F> OSGi<F> apply(Function5<A, B, C, D, E, F>
fun, OSGi<A> a, OSGi<B> b, OSGi<C> c, OSGi<D> d, OSGi<E> e)
{
+		return e.applyTo(OSGi.apply((A aa, B bb, C cc, D dd) -> fun.curried().apply(aa).apply(bb).apply(cc).apply(dd),
a, b, c, d));
+	}
+
+	public static <A, B, C, D, E, F, G> OSGi<G> apply(Function6<A, B, C, D, E,
F, G> fun, OSGi<A> a, OSGi<B> b, OSGi<C> c, OSGi<D> d, OSGi<E>
e, OSGi<F> f) {
+		return f.applyTo(OSGi.apply((A aa, B bb, C cc, D dd, E ee) -> fun.curried().apply(aa).apply(bb).apply(cc).apply(dd).apply(ee),
a, b, c, d, e));
+	}
+
 }

Modified: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/JustOSGiImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/JustOSGiImpl.java?rev=1797036&r1=1797035&r2=1797036&view=diff
==============================================================================
--- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/JustOSGiImpl.java
(original)
+++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/JustOSGiImpl.java
Wed May 31 13:23:49 2017
@@ -21,6 +21,8 @@ package org.apache.aries.osgi.functional
 import org.apache.aries.osgi.functional.OSGi;
 import org.apache.aries.osgi.functional.OSGiResult;
 
+import java.util.ArrayList;
+import java.util.IdentityHashMap;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Consumer;
 import java.util.function.Function;
@@ -94,4 +96,52 @@ public class JustOSGiImpl<T> extends OSG
 				});
 		});
 	}
+
+/*
+	@Override
+	public <S> OSGi<S> applyTo(OSGi<Function<T, S>> fun) {
+		return new OSGiImpl<>(bundleContext -> {
+			Pipe<Tuple<S>, Tuple<S>> added = Pipe.create();
+
+			Consumer<Tuple<S>> addedSource = added.getSource();
+
+			Pipe<Tuple<S>, Tuple<S>> removed = Pipe.create();
+
+			Consumer<Tuple<S>> removedSource = removed.getSource();
+
+			IdentityHashMap<Function<T, S>, Tuple<S>> identityMap =
+				new IdentityHashMap<>();
+
+			OSGi<Void> next = fun.foreach(
+				f -> {
+					Tuple<S> tuple = Tuple.create(f.apply(_t));
+
+					identityMap.put(f, tuple);
+
+					addedSource.accept(tuple);
+				},
+				f -> {
+					Tuple<S> tuple = identityMap.remove(f);
+
+					if (tuple != null) {
+						removedSource.accept(tuple);
+					}
+				});
+
+			AtomicReference<OSGiResult<Void>> atomicReference =
+				new AtomicReference<>();
+
+			return new OSGiResultImpl<>(
+				added, removed,
+				() -> atomicReference.set(next.run(bundleContext)),
+				() -> {
+					identityMap.forEach((f, t) -> removedSource.accept(t));
+
+					identityMap.clear();
+
+					atomicReference.get().close();
+				});
+		});
+	}
+*/
 }

Modified: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/OSGiImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/OSGiImpl.java?rev=1797036&r1=1797035&r2=1797036&view=diff
==============================================================================
--- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/OSGiImpl.java
(original)
+++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/OSGiImpl.java
Wed May 31 13:23:49 2017
@@ -26,7 +26,9 @@ import org.osgi.framework.InvalidSyntaxE
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.IdentityHashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
@@ -337,6 +339,193 @@ public class OSGiImpl<T> implements OSGi
 		});
 	}
 
+	private static class Pair<X, Y> {
+		private final X _first;
+		private final Y _second;
+
+		public Pair(X first, Y second) {
+			_first = first;
+			_second = second;
+		}
+
+		public X getFirst() {
+			return _first;
+		}
+
+		public Y getSecond() {
+			return _second;
+		}
+
+		@Override
+		public boolean equals(Object o) {
+			if (this == o) return true;
+			if (o == null || getClass() != o.getClass()) return false;
+
+			Pair<?, ?> pair = (Pair<?, ?>) o;
+
+			return _first.equals(pair._first);
+		}
+
+		@Override
+		public int hashCode() {
+			return _first.hashCode();
+		}
+	}
+
+	@Override
+	public <S> OSGi<S> applyTo(OSGi<Function<T, S>> fun) {
+		return new OSGiImpl<>(
+			((bundleContext) -> {
+				Map<Tuple<T>, List<Pair<Function<T, S>, Tuple<S>>>>
identities =
+					new HashMap<>();
+
+				Map<Function<T, S>, List<Pair<Tuple<T>, Tuple<S>>>>
funs =
+					new IdentityHashMap<>();
+
+				AtomicReference<OSGiResult<?>> myCloseReference =
+					new AtomicReference<>();
+
+				AtomicReference<OSGiResult<?>> otherCloseReference =
+					new AtomicReference<>();
+
+				Pipe<Tuple<S>, Tuple<S>> added = Pipe.create();
+
+				Consumer<Tuple<S>> addedSource = added.getSource();
+
+				Pipe<Tuple<S>, Tuple<S>> removed = Pipe.create();
+
+				Consumer<Tuple<S>> removedSource = removed.getSource();
+
+				OSGiResultImpl<S> osgiResult = new OSGiResultImpl<>(
+					added, removed, null,
+					() -> {
+						synchronized (identities) {
+							identities.values().forEach(i ->
+								i.forEach(
+									p -> removedSource.accept(
+										p.getSecond())));
+
+							funs.clear();
+						}
+
+						myCloseReference.get().close();
+
+						otherCloseReference.get().close();
+					});
+
+				osgiResult.start = () -> {
+					OSGiResultImpl<T> or1 = _operation.run(bundleContext);
+
+					myCloseReference.set(or1);
+
+					or1.added.map(t -> {
+						synchronized (identities) {
+							identities.put(t, new ArrayList<>());
+
+							funs.keySet().forEach(f ->
+								processAdded(
+									identities, funs, addedSource, f, t));
+
+							return null;
+						}
+					});
+
+					or1.removed.map(t -> {
+						synchronized (identities) {
+							List<Pair<Function<T, S>, Tuple<S>>> remove =
+								identities.remove(t);
+
+							if (remove == null) {
+								return null;
+							}
+
+							remove.forEach(p -> {
+								List<Pair<Tuple<T>, Tuple<S>>> pairs = funs.get(
+									p.getFirst());
+
+								if (pairs == null) {
+									return;
+								}
+
+								pairs.remove(new Pair<>(t, null));
+
+								removedSource.accept(p.getSecond());
+							});
+						}
+
+						return null;
+					});
+
+					OSGiResult<Void> or2 = fun.foreach(
+						f -> {
+							synchronized (identities) {
+								funs.put(f, new ArrayList<>());
+
+								identities.keySet().forEach(
+									t -> processAdded(
+										identities, funs, addedSource, f, t));
+							}
+						},
+						f -> {
+							synchronized (identities) {
+								List<Pair<Tuple<T>, Tuple<S>>> remove = funs.remove(f);
+
+								if (remove == null) {
+									return;
+								}
+
+								remove.forEach(p -> {
+									List<Pair<Function<T, S>, Tuple<S>>> pairs =
+										identities.get(p.getFirst());
+
+									Iterator<Pair<Function<T, S>, Tuple<S>>> iterator =
+										pairs.iterator();
+
+									while (iterator.hasNext()) {
+										Pair<Function<T, S>, Tuple<S>> next = iterator.next();
+
+										if (next.getFirst() == f) {
+											iterator.remove();
+
+											break;
+										}
+									}
+
+									removedSource.accept(p.getSecond());
+								});
+							}
+						}).run(bundleContext);
+
+					or1.start.run();
+
+					otherCloseReference.set(or2);
+				};
+
+				return osgiResult;
+			}
+			));
+	}
+
+	private <S> void processAdded(
+		Map<Tuple<T>, List<Pair<Function<T, S>, Tuple<S>>>>
identities,
+		Map<Function<T, S>, List<Pair<Tuple<T>, Tuple<S>>>>
funs,
+		Consumer<Tuple<S>> addedSource, Function<T, S> f, Tuple<T> t) {
+
+		S result = f.apply(t.t);
+
+		Tuple<S> tuple = Tuple.create(result);
+
+		List<Pair<Function<T, S>, Tuple<S>>> tuples = identities.get(t);
+
+		tuples.add(new Pair<>(f, tuple));
+
+		List<Pair<Tuple<T>, Tuple<S>>> tuples2 = funs.get(f);
+
+		tuples2.add(new Pair<>(t, tuple));
+
+		addedSource.accept(tuple);
+	}
+
 	static class RouterImpl<T> implements Router<T> {
 
 		RouterImpl(

Modified: aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/Tuple.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/Tuple.java?rev=1797036&r1=1797035&r2=1797036&view=diff
==============================================================================
--- aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/Tuple.java
(original)
+++ aries/trunk/component-dsl/component-dsl/src/main/java/org/apache/aries/osgi/functional/internal/Tuple.java
Wed May 31 13:23:49 2017
@@ -48,4 +48,18 @@ class Tuple<T> implements Event<T> {
 		return t;
 	}
 
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+		if (o == null || getClass() != o.getClass()) return false;
+
+		Tuple<?> tuple = (Tuple<?>) o;
+
+		return original == tuple.original;
+	}
+
+	@Override
+	public int hashCode() {
+		return original.hashCode();
+	}
 }

Modified: aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/osgi/functional/test/ComponentTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/osgi/functional/test/ComponentTest.java?rev=1797036&r1=1797035&r2=1797036&view=diff
==============================================================================
--- aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/osgi/functional/test/ComponentTest.java
(original)
+++ aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/osgi/functional/test/ComponentTest.java
Wed May 31 13:23:49 2017
@@ -39,8 +39,10 @@ import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.function.Consumer;
 
+import static org.apache.aries.osgi.functional.OSGi.apply;
 import static org.apache.aries.osgi.functional.OSGi.bundleContext;
 import static org.apache.aries.osgi.functional.OSGi.configurations;
 import static org.apache.aries.osgi.functional.OSGi.just;
@@ -77,7 +79,7 @@ public class ComponentTest {
     }
 
     @Test
-    public void testComponent() {
+    public void testComponent() throws IOException {
         OSGi<?> program =
             configurations("org.components.MyComponent").flatMap(props ->
             services(Service.class).flatMap(ms ->
@@ -104,13 +106,127 @@ public class ComponentTest {
                 put("service.pid", "org.components.MyComponent");
             }});
 
+        Configuration factoryConfiguration = null;
+
         try (OSGiResult<?> run = program.run(_bundleContext)) {
-            Configuration factoryConfiguration =
+            factoryConfiguration = _configurationAdmin.createFactoryConfiguration(
+                "org.components.MyComponent");
+            factoryConfiguration.update(new Hashtable<>());
+
+            countDownLatch.await(10, TimeUnit.SECONDS);
+
+            assertNull(serviceTracker.getService());
+
+            ServiceRegistration<Service> serviceRegistration =
+                _bundleContext.registerService(
+                    Service.class, new Service(), new Hashtable<>());
+
+            Component component = serviceTracker.waitForService(10 * 1000);
+
+            assertNotNull(component);
+
+            assertNull(component.getOptional());
+
+            ServiceRegistration<ServiceOptional> serviceRegistration2 =
+                _bundleContext.registerService(
+                    ServiceOptional.class, new ServiceOptional(),
+                    new Hashtable<>());
+
+            Thread.sleep(1000L);
+
+            assertNotNull(component.getOptional());
+
+            ServiceOptional serviceOptional = new ServiceOptional();
+
+            ServiceRegistration<ServiceOptional> serviceRegistration3 =
+                _bundleContext.registerService(
+                    ServiceOptional.class, serviceOptional,
+                    new Hashtable<String, Object>() {{
+                        put("service.ranking", 1);
+                    }});
+
+            assertEquals(serviceOptional, component.getOptional());
+
+            serviceRegistration3.unregister();
+
+            assertNotNull(component.getOptional());
+
+            serviceRegistration2.unregister();
+
+            assertNull(component.getOptional());
+
+            ServiceRegistration<ServiceForList> serviceRegistration4 =
+                _bundleContext.registerService(
+                    ServiceForList.class, new ServiceForList(),
+                    new Hashtable<>());
+
+            ServiceRegistration<ServiceForList> serviceRegistration5 =
+                _bundleContext.registerService(
+                    ServiceForList.class, new ServiceForList(),
+                    new Hashtable<>());
+
+            assertEquals(2, component.getServiceForLists().size());
+
+            serviceRegistration4.unregister();
+
+            assertEquals(1, component.getServiceForLists().size());
+
+            serviceRegistration5.unregister();
+
+            assertEquals(0, component.getServiceForLists().size());
+
+            serviceRegistration.unregister();
+
+            assertNull(serviceTracker.getService());
+        }
+        catch (IOException ioe) {
+
+        }
+        catch (InterruptedException e) {
+            Assert.fail("Timeout waiting for configuration");
+        }
+        finally {
+            serviceTracker.close();
+
+            if (factoryConfiguration != null) {
+                factoryConfiguration.delete();
+            }
+        }
+    }
+
+    @Test
+    public void testComponentApplicative() throws IOException, TimeoutException {
+        OSGi<?> program =
+            apply(
+                Component::new,
+                configurations("org.components.MyComponent"),
+                services(Service.class)).
+                flatMap(
+                    comp ->
+                register(Component.class, comp, new HashMap<>()).distribute(
+                    ign -> dynamic(
+                        highestService(ServiceOptional.class),
+                        comp::setOptional, c -> comp.setOptional(null)),
+                    ign -> dynamic(
+                        services(ServiceForList.class),
+                        comp::addService, comp::removeService)
+                ));
+
+        ServiceTracker<Component, Component> serviceTracker =
+            new ServiceTracker<>(_bundleContext, Component.class, null);
+
+        serviceTracker.open();
+
+        Configuration factoryConfiguration = null;
+
+        try (OSGiResult<?> run = program.run(_bundleContext)) {
+            factoryConfiguration =
                 _configurationAdmin.createFactoryConfiguration(
                     "org.components.MyComponent");
+
             factoryConfiguration.update(new Hashtable<>());
 
-            countDownLatch.await(10, TimeUnit.SECONDS);
+            Thread.sleep(1000);
 
             assertNull(serviceTracker.getService());
 
@@ -122,6 +238,30 @@ public class ComponentTest {
 
             assertNotNull(component);
 
+            ServiceRegistration<Service> serviceRegistration10 =
+                _bundleContext.registerService(
+                    Service.class, new Service(), new Hashtable<>());
+
+            assertEquals(2, serviceTracker.getServiceReferences().length);
+
+            Configuration factoryConfiguration2 =
+                _configurationAdmin.createFactoryConfiguration(
+                    "org.components.MyComponent");
+
+            factoryConfiguration2.update(new Hashtable<>());
+
+            Thread.sleep(1000);
+
+            assertEquals(4, serviceTracker.getServiceReferences().length);
+
+            factoryConfiguration2.delete();
+
+            Thread.sleep(1000);
+
+            assertEquals(2, serviceTracker.getServiceReferences().length);
+
+            serviceRegistration10.unregister();
+
             assertNull(component.getOptional());
 
             ServiceRegistration<ServiceOptional> serviceRegistration2 =
@@ -184,9 +324,14 @@ public class ComponentTest {
         }
         finally {
             serviceTracker.close();
+
+            if (factoryConfiguration != null) {
+                factoryConfiguration.delete();
+            }
         }
     }
 
+
     private static <T> OSGi<T> highestService(Class<T> clazz) {
         return highest(clazz).flatMap(sr ->
         bundleContext().flatMap(bc ->

Modified: aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/osgi/functional/test/DSLTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/osgi/functional/test/DSLTest.java?rev=1797036&r1=1797035&r2=1797036&view=diff
==============================================================================
--- aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/osgi/functional/test/DSLTest.java
(original)
+++ aries/trunk/component-dsl/itests/src/main/java/org/apache/aries/osgi/functional/test/DSLTest.java
Wed May 31 13:23:49 2017
@@ -39,6 +39,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
 
 import static org.apache.aries.osgi.functional.OSGi.configuration;
 import static org.apache.aries.osgi.functional.OSGi.configurations;
@@ -547,6 +548,29 @@ public class DSLTest {
 
     }
 
+    @Test
+    public void testApplicativeApplyTo() {
+        AtomicInteger integer = new AtomicInteger(0);
+
+        OSGi<Integer> program = just(5).applyTo(just((i) -> i + 5));
+
+        program.run(bundleContext, integer::set);
+
+        assertEquals(10, integer.get());
+    }
+
+    @Test
+    public void testApply() {
+        AtomicInteger integer = new AtomicInteger(0);
+
+        OSGi<Integer> program = OSGi.apply(
+            (a, b, c) -> a + b + c, just(5), just(5), just(5));
+
+        program.run(bundleContext, integer::set);
+
+        assertEquals(15, integer.get());
+    }
+
     private class Service {}
 
 }



Mime
View raw message