addFactory method for MarkwonSpansFactory
This commit is contained in:
		
							parent
							
								
									740ff1013c
								
							
						
					
					
						commit
						7f3f3368be
					
				| @ -34,6 +34,15 @@ public interface MarkwonSpansFactory { | ||||
|         @NonNull | ||||
|         <N extends Node> Builder setFactory(@NonNull Class<N> node, @Nullable SpanFactory factory); | ||||
| 
 | ||||
|         /** | ||||
|          * Helper method to add a {@link SpanFactory} for a Node. This method will merge existing | ||||
|          * {@link SpanFactory} with the specified one. | ||||
|          * | ||||
|          * @since 3.0.1-SNAPSHOT | ||||
|          */ | ||||
|         @NonNull | ||||
|         <N extends Node> Builder addFactory(@NonNull Class<N> node, @NonNull SpanFactory factory); | ||||
| 
 | ||||
|         /** | ||||
|          * Can be useful when <em>enhancing</em> an already defined SpanFactory with another one. | ||||
|          */ | ||||
|  | ||||
| @ -5,8 +5,10 @@ import android.support.annotation.Nullable; | ||||
| 
 | ||||
| import org.commonmark.node.Node; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| /** | ||||
| @ -52,6 +54,27 @@ class MarkwonSpansFactoryImpl implements MarkwonSpansFactory { | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         @NonNull | ||||
|         @Override | ||||
|         public <N extends Node> Builder addFactory(@NonNull Class<N> node, @NonNull SpanFactory factory) { | ||||
|             // if there is no factory registered for this node -> just add it | ||||
|             final SpanFactory existing = factories.get(node); | ||||
|             if (existing == null) { | ||||
|                 factories.put(node, factory); | ||||
|             } else { | ||||
|                 // existing span factory can be of CompositeSpanFactory at this point -> append to it | ||||
|                 if (existing instanceof CompositeSpanFactory) { | ||||
|                     ((CompositeSpanFactory) existing).factories.add(factory); | ||||
|                 } else { | ||||
|                     // if it's not composite at this point -> make it | ||||
|                     final CompositeSpanFactory compositeSpanFactory = | ||||
|                             new CompositeSpanFactory(existing, factory); | ||||
|                     factories.put(node, compositeSpanFactory); | ||||
|                 } | ||||
|             } | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         @Nullable | ||||
|         @Override | ||||
|         public <N extends Node> SpanFactory getFactory(@NonNull Class<N> node) { | ||||
| @ -74,4 +97,28 @@ class MarkwonSpansFactoryImpl implements MarkwonSpansFactory { | ||||
|             return new MarkwonSpansFactoryImpl(Collections.unmodifiableMap(factories)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     static class CompositeSpanFactory implements SpanFactory { | ||||
| 
 | ||||
|         final List<SpanFactory> factories; | ||||
| 
 | ||||
|         CompositeSpanFactory(@NonNull SpanFactory first, @NonNull SpanFactory second) { | ||||
|             this.factories = new ArrayList<>(3); | ||||
|             this.factories.add(first); | ||||
|             this.factories.add(second); | ||||
|         } | ||||
| 
 | ||||
|         @Nullable | ||||
|         @Override | ||||
|         public Object getSpans(@NonNull MarkwonConfiguration configuration, @NonNull RenderProps props) { | ||||
|             // please note that we do not check it factory itself returns an array of spans, | ||||
|             // as this behaviour is supported now (previously we supported only a single-level array) | ||||
|             final int length = factories.size(); | ||||
|             final Object[] out = new Object[length]; | ||||
|             for (int i = 0; i < length; i++) { | ||||
|                 out[i] = factories.get(i).getSpans(configuration, props); | ||||
|             } | ||||
|             return out; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -13,13 +13,18 @@ import org.junit.runner.RunWith; | ||||
| import org.robolectric.RobolectricTestRunner; | ||||
| import org.robolectric.annotation.Config; | ||||
| 
 | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| 
 | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| import static org.junit.Assert.assertNull; | ||||
| import static org.junit.Assert.assertTrue; | ||||
| import static org.junit.Assert.fail; | ||||
| import static org.mockito.ArgumentMatchers.any; | ||||
| import static org.mockito.Mockito.mock; | ||||
| import static org.mockito.Mockito.times; | ||||
| import static org.mockito.Mockito.verify; | ||||
| 
 | ||||
| @RunWith(RobolectricTestRunner.class) | ||||
| @Config(manifest = Config.NONE) | ||||
| @ -87,4 +92,58 @@ public class MarkwonSpansFactoryImplTest { | ||||
|             assertNull(factory.get(type)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void composite_span_factory() { | ||||
|         // validate that composite span factory returns (calls) all span-factories | ||||
| 
 | ||||
|         final SpanFactory first = mock(SpanFactory.class); | ||||
|         final SpanFactory second = mock(SpanFactory.class); | ||||
| 
 | ||||
|         final MarkwonSpansFactoryImpl.CompositeSpanFactory factory = | ||||
|                 new MarkwonSpansFactoryImpl.CompositeSpanFactory(first, second); | ||||
| 
 | ||||
|         final Object spans = factory.getSpans(mock(MarkwonConfiguration.class), mock(RenderProps.class)); | ||||
|         assertNotNull(spans); | ||||
|         assertTrue(spans.getClass().isArray()); | ||||
|         assertEquals(2, ((Object[]) spans).length); | ||||
| 
 | ||||
|         verify(first, times(1)).getSpans(any(MarkwonConfiguration.class), any(RenderProps.class)); | ||||
|         verify(second, times(1)).getSpans(any(MarkwonConfiguration.class), any(RenderProps.class)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void builder_add_factory() { | ||||
|         // here is what we should validate: | ||||
|         // * if we call addFactory and there is none already -> supplied factory | ||||
|         // * if there is | ||||
|         // * * if not composite -> make composite | ||||
|         // * * if composite -> add to it | ||||
| 
 | ||||
|         final MarkwonSpansFactoryImpl.BuilderImpl builder = new MarkwonSpansFactoryImpl.BuilderImpl(); | ||||
| 
 | ||||
|         final SpanFactory first = mock(SpanFactory.class); | ||||
|         final SpanFactory second = mock(SpanFactory.class); | ||||
|         final SpanFactory third = mock(SpanFactory.class); | ||||
| 
 | ||||
|         final Class<Node> node = Node.class; | ||||
| 
 | ||||
|         // assert none yet | ||||
|         assertNull(builder.getFactory(node)); | ||||
| 
 | ||||
|         // add first, none yet -> it should be added without modifications | ||||
|         builder.addFactory(node, first); | ||||
|         assertEquals(first, builder.getFactory(node)); | ||||
| 
 | ||||
|         // add second -> composite factory will be created | ||||
|         builder.addFactory(node, second); | ||||
|         final MarkwonSpansFactoryImpl.CompositeSpanFactory compositeSpanFactory = | ||||
|                 (MarkwonSpansFactoryImpl.CompositeSpanFactory) builder.getFactory(node); | ||||
|         assertNotNull(compositeSpanFactory); | ||||
|         assertEquals(Arrays.asList(first, second), compositeSpanFactory.factories); | ||||
| 
 | ||||
|         builder.addFactory(node, third); | ||||
|         assertEquals(compositeSpanFactory, builder.getFactory(node)); | ||||
|         assertEquals(Arrays.asList(first, second, third), compositeSpanFactory.factories); | ||||
|     } | ||||
| } | ||||
| @ -156,6 +156,12 @@ public class CorePluginTest { | ||||
|                 return this; | ||||
|             } | ||||
| 
 | ||||
|             @NonNull | ||||
|             @Override | ||||
|             public <N extends Node> MarkwonSpansFactory.Builder addFactory(@NonNull Class<N> node, @NonNull SpanFactory factory) { | ||||
|                 throw new RuntimeException(); | ||||
|             } | ||||
| 
 | ||||
|             @Nullable | ||||
|             @Override | ||||
|             public <N extends Node> SpanFactory getFactory(@NonNull Class<N> node) { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dimitry Ivanov
						Dimitry Ivanov