1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.repository;
25
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.FileOutputStream;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.OutputStream;
32 import java.net.URL;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Set;
40 import java.util.Stack;
41 import net.jcip.annotations.Immutable;
42 import net.jcip.annotations.NotThreadSafe;
43 import org.modeshape.common.collection.Problems;
44 import org.modeshape.common.collection.SimpleProblems;
45 import org.modeshape.common.component.ClassLoaderFactory;
46 import org.modeshape.common.component.StandardClassLoaderFactory;
47 import org.modeshape.common.util.CheckArg;
48 import org.modeshape.common.xml.StreamingContentHandler;
49 import org.modeshape.graph.DnaExecutionContext;
50 import org.modeshape.graph.ExecutionContext;
51 import org.modeshape.graph.Graph;
52 import org.modeshape.graph.Location;
53 import org.modeshape.graph.Node;
54 import org.modeshape.graph.Subgraph;
55 import org.modeshape.graph.SubgraphNode;
56 import org.modeshape.graph.Workspace;
57 import org.modeshape.graph.connector.RepositorySource;
58 import org.modeshape.graph.connector.inmemory.InMemoryRepositorySource;
59 import org.modeshape.graph.mimetype.MimeTypeDetector;
60 import org.modeshape.graph.property.Name;
61 import org.modeshape.graph.property.NamespaceRegistry;
62 import org.modeshape.graph.property.Path;
63 import org.modeshape.graph.property.PathExpression;
64 import org.modeshape.graph.property.PathNotFoundException;
65 import org.modeshape.graph.property.Property;
66 import org.modeshape.graph.property.ValueFactory;
67 import org.modeshape.graph.property.basic.RootPath;
68 import org.modeshape.graph.request.InvalidWorkspaceException;
69 import org.modeshape.graph.request.ReadBranchRequest;
70 import org.modeshape.graph.sequencer.StreamSequencer;
71 import org.xml.sax.ContentHandler;
72 import org.xml.sax.SAXException;
73 import org.xml.sax.helpers.AttributesImpl;
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 @SuppressWarnings( "deprecation" )
91 @NotThreadSafe
92 public class ModeShapeConfiguration {
93
94 public static final String DEFAULT_WORKSPACE_NAME = "";
95 public static final String DEFAULT_PATH = "/";
96 public static final String DEFAULT_CONFIGURATION_SOURCE_NAME = "ModeShape Configuration Repository";
97
98 private final ExecutionContext context;
99 private final Problems problems = new SimpleProblems();
100 private ConfigurationDefinition configurationContent;
101 private Graph.Batch changes;
102
103 private final Map<String, SequencerDefinition<? extends ModeShapeConfiguration>> sequencerDefinitions = new HashMap<String, SequencerDefinition<? extends ModeShapeConfiguration>>();
104 private final Map<String, RepositorySourceDefinition<? extends ModeShapeConfiguration>> repositorySourceDefinitions = new HashMap<String, RepositorySourceDefinition<? extends ModeShapeConfiguration>>();
105 private final Map<String, MimeTypeDetectorDefinition<? extends ModeShapeConfiguration>> mimeTypeDetectorDefinitions = new HashMap<String, MimeTypeDetectorDefinition<? extends ModeShapeConfiguration>>();
106
107
108
109
110 public ModeShapeConfiguration() {
111 this(new ExecutionContext());
112 }
113
114
115
116
117
118
119
120 public ModeShapeConfiguration( ExecutionContext context ) {
121 CheckArg.isNotNull(context, "context");
122 this.context = context;
123
124
125 InMemoryRepositorySource source = new InMemoryRepositorySource();
126 source.setName(DEFAULT_CONFIGURATION_SOURCE_NAME);
127 source.setDefaultWorkspaceName(DEFAULT_WORKSPACE_NAME);
128
129
130 configurationContent = new ConfigurationDefinition("dna", source, null, null, context, null);
131 }
132
133
134
135
136
137
138
139 public ModeShapeConfiguration withName( String name ) {
140 if (name != null) name = "dna";
141 configurationContent = configurationContent.with(name);
142 return this;
143 }
144
145
146
147
148
149
150
151
152
153
154 public ModeShapeConfiguration loadFrom( String pathToConfigurationFile ) throws IOException, SAXException {
155 CheckArg.isNotEmpty(pathToConfigurationFile, "pathToConfigurationFile");
156 return loadFrom(pathToConfigurationFile, DEFAULT_PATH);
157 }
158
159
160
161
162
163
164
165
166
167
168
169
170 public ModeShapeConfiguration loadFrom( String pathToConfigurationFile,
171 String path ) throws IOException, SAXException {
172 CheckArg.isNotEmpty(pathToConfigurationFile, "pathToConfigurationFile");
173 return loadFrom(new File(pathToConfigurationFile), path);
174 }
175
176
177
178
179
180
181
182
183
184
185 public ModeShapeConfiguration loadFrom( File configurationFile ) throws IOException, SAXException {
186 CheckArg.isNotNull(configurationFile, "configurationFile");
187 return loadFrom(configurationFile, DEFAULT_PATH);
188 }
189
190
191
192
193
194
195
196
197
198
199
200
201 public ModeShapeConfiguration loadFrom( File configurationFile,
202 String path ) throws IOException, SAXException {
203 CheckArg.isNotNull(configurationFile, "configurationFile");
204 InputStream stream = new FileInputStream(configurationFile);
205 try {
206 return loadFrom(stream, path);
207 } finally {
208 stream.close();
209 }
210 }
211
212
213
214
215
216
217
218
219
220
221 public ModeShapeConfiguration loadFrom( URL urlToConfigurationFile ) throws IOException, SAXException {
222 CheckArg.isNotNull(urlToConfigurationFile, "urlToConfigurationFile");
223 return loadFrom(urlToConfigurationFile, DEFAULT_PATH);
224 }
225
226
227
228
229
230
231
232
233
234
235
236
237 public ModeShapeConfiguration loadFrom( URL urlToConfigurationFile,
238 String path ) throws IOException, SAXException {
239 CheckArg.isNotNull(urlToConfigurationFile, "urlToConfigurationFile");
240 InputStream stream = urlToConfigurationFile.openStream();
241 try {
242 return loadFrom(stream, path);
243 } finally {
244 stream.close();
245 }
246 }
247
248
249
250
251
252
253
254
255
256
257 public ModeShapeConfiguration loadFrom( InputStream configurationFileInputStream ) throws IOException, SAXException {
258 CheckArg.isNotNull(configurationFileInputStream, "configurationFileInputStream");
259 return loadFrom(configurationFileInputStream, DEFAULT_PATH);
260 }
261
262
263
264
265
266
267
268
269
270
271
272
273 public ModeShapeConfiguration loadFrom( InputStream configurationFileInputStream,
274 String path ) throws IOException, SAXException {
275 CheckArg.isNotNull(configurationFileInputStream, "configurationFileInputStream");
276
277
278 InMemoryRepositorySource source = new InMemoryRepositorySource();
279 source.setName(DEFAULT_CONFIGURATION_SOURCE_NAME);
280 source.setDefaultWorkspaceName(DEFAULT_WORKSPACE_NAME);
281
282
283 Path pathToParent = path(path != null ? path : DEFAULT_PATH);
284 Graph graph = Graph.create(source, context);
285 graph.importXmlFrom(configurationFileInputStream).skippingRootElement(true).into(pathToParent);
286
287
288 configurationContent = new ConfigurationDefinition(configurationContent.getName(), source, null, pathToParent, context,
289 null);
290 return this;
291 }
292
293
294
295
296
297
298
299
300
301
302
303 public ModeShapeConfiguration loadFrom( RepositorySource source ) {
304 return loadFrom(source, null, null);
305 }
306
307
308
309
310
311
312
313
314
315
316
317
318 public ModeShapeConfiguration loadFrom( RepositorySource source,
319 String workspaceName ) {
320 CheckArg.isNotNull(source, "source");
321 return loadFrom(source, workspaceName, null);
322 }
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337 public ModeShapeConfiguration loadFrom( RepositorySource source,
338 String workspaceName,
339 String pathInWorkspace ) {
340 CheckArg.isNotNull(source, "source");
341
342
343 Graph graph = Graph.create(source, context);
344 if (workspaceName != null) {
345 Workspace workspace = null;
346 try {
347 workspace = graph.useWorkspace(workspaceName);
348 } catch (InvalidWorkspaceException e) {
349
350 workspace = graph.createWorkspace().named(workspaceName);
351 }
352 assert workspace.getRoot() != null;
353 }
354
355
356 Path path = pathInWorkspace != null ? path(pathInWorkspace) : path(DEFAULT_PATH);
357 Node parent = graph.getNodeAt(path);
358 assert parent != null;
359
360
361 configurationContent = new ConfigurationDefinition(configurationContent.getName(), source, workspaceName, path, context,
362 null);
363 return this;
364 }
365
366
367
368
369
370
371
372
373
374 public void storeTo( String file ) throws SAXException, IOException {
375 storeTo(new File(file));
376 }
377
378
379
380
381
382
383
384
385
386 public void storeTo( File file ) throws SAXException, IOException {
387 OutputStream os = null;
388 try {
389 os = new FileOutputStream(file);
390 storeTo(new StreamingContentHandler(os));
391 } finally {
392 if (os != null) os.close();
393 }
394 }
395
396
397
398
399
400
401
402
403 public void storeTo( OutputStream os ) throws SAXException {
404 storeTo(new StreamingContentHandler(os));
405 }
406
407
408
409
410
411
412
413
414 public void storeTo( ContentHandler handler ) throws SAXException {
415 Subgraph allContent = configurationGraph().getSubgraphOfDepth(ReadBranchRequest.NO_MAXIMUM_DEPTH).at("/");
416
417 Set<NamespaceRegistry.Namespace> namespaces = this.context.getNamespaceRegistry().getNamespaces();
418 Stack<String> mappedNamespacePrefixes = new Stack<String>();
419
420 handler.startDocument();
421
422 for (NamespaceRegistry.Namespace namespace : namespaces) {
423 handler.startPrefixMapping(namespace.getPrefix(), namespace.getNamespaceUri());
424 mappedNamespacePrefixes.push(namespace.getPrefix());
425 }
426
427 exportNode(handler, allContent, allContent.getRoot());
428 while (!mappedNamespacePrefixes.isEmpty()) {
429 handler.endPrefixMapping(mappedNamespacePrefixes.pop());
430 }
431
432 handler.endDocument();
433 }
434
435 private void exportNode( ContentHandler handler,
436 Subgraph subgraph,
437 SubgraphNode node ) throws SAXException {
438
439
440 NamespaceRegistry registry = this.context.getNamespaceRegistry();
441 ValueFactory<String> stringFactory = this.context.getValueFactories().getStringFactory();
442
443 AttributesImpl atts = new AttributesImpl();
444
445 for (Property prop : node.getProperties()) {
446 Name name = prop.getName();
447
448 StringBuilder buff = new StringBuilder();
449 boolean first = true;
450
451 for (Object rawValue : prop) {
452 if (first) {
453 first = false;
454 } else {
455 buff.append(",");
456 }
457 buff.append(stringFactory.create(rawValue));
458 }
459
460 atts.addAttribute(name.getNamespaceUri(), name.getLocalName(), name.getString(registry), "string", buff.toString());
461 }
462
463
464 Name nodeName;
465 Path nodePath = node.getLocation().getPath();
466 if (nodePath.isRoot()) {
467 nodeName = name("configuration");
468 } else {
469 nodeName = node.getLocation().getPath().getLastSegment().getName();
470 }
471 String uri = nodeName.getNamespaceUri();
472 String localName = nodeName.getLocalName();
473 String qName = nodeName.getString(registry);
474 handler.startElement(uri, localName, qName, atts);
475
476
477 for (Location childLocation : node.getChildren()) {
478 exportNode(handler, subgraph, subgraph.getNode(childLocation));
479 }
480
481
482 handler.endElement(uri, localName, qName);
483
484 }
485
486
487
488
489
490
491 public ConfigurationDefinition getConfigurationDefinition() {
492 return configurationContent;
493 }
494
495 protected ExecutionContext getExecutionContext() {
496 return configurationContent.getContext();
497 }
498
499 protected Path path() {
500 return configurationContent.getPath();
501 }
502
503 protected Path path( String path ) {
504 return context.getValueFactories().getPathFactory().create(path);
505 }
506
507 protected Name name( String name ) {
508 return context.getValueFactories().getNameFactory().create(name);
509 }
510
511
512
513
514
515
516 public Problems getProblems() {
517 return problems;
518 }
519
520 protected Graph configurationGraph() {
521 ConfigurationDefinition content = getConfigurationDefinition();
522 Graph graph = Graph.create(content.getRepositorySource(), content.getContext());
523 if (content.getWorkspace() != null) {
524 graph.useWorkspace(content.getWorkspace());
525 }
526
527 return graph;
528 }
529
530 protected Graph.Batch changes() {
531 if (changes == null) {
532 changes = configurationGraph().batch();
533 }
534 return changes;
535 }
536
537
538
539
540
541
542
543
544 public boolean hasChanges() {
545 Graph.Batch changes = this.changes;
546 return changes != null && changes.isExecuteRequired();
547 }
548
549
550
551
552
553
554
555 public ModeShapeConfiguration save() {
556 Graph.Batch changes = this.changes;
557 if (changes != null && changes.isExecuteRequired()) {
558 changes.execute();
559 }
560 this.changes = null;
561 sequencerDefinitions.clear();
562 mimeTypeDetectorDefinitions.clear();
563 repositorySourceDefinitions.clear();
564 return this;
565 }
566
567
568
569
570
571
572
573
574
575
576
577
578
579 public ModeShapeConfiguration withClassLoaderFactory( ClassLoaderFactory classLoaderFactory ) {
580 this.configurationContent = this.configurationContent.with(classLoaderFactory);
581 return this;
582 }
583
584 protected Set<String> getNamesOfComponentsUnder( Name parentName ) {
585 Set<String> names = new HashSet<String>();
586 try {
587 ConfigurationDefinition content = this.getConfigurationDefinition();
588 Path path = context.getValueFactories().getPathFactory().create(content.getPath(), parentName);
589 for (Location child : content.graph().getChildren().of(path)) {
590 names.add(child.getPath().getLastSegment().getString(context.getNamespaceRegistry()));
591 }
592 } catch (PathNotFoundException e) {
593
594 }
595 return names;
596 }
597
598
599
600
601
602
603 public Set<MimeTypeDetectorDefinition<? extends ModeShapeConfiguration>> mimeTypeDetectors() {
604
605 Set<String> names = getNamesOfComponentsUnder(ModeShapeLexicon.MIME_TYPE_DETECTORS);
606 names.addAll(this.mimeTypeDetectorDefinitions.keySet());
607 Set<MimeTypeDetectorDefinition<? extends ModeShapeConfiguration>> results = new HashSet<MimeTypeDetectorDefinition<? extends ModeShapeConfiguration>>();
608 for (String name : names) {
609 results.add(mimeTypeDetector(name));
610 }
611 return Collections.unmodifiableSet(results);
612 }
613
614
615
616
617
618
619 public Set<RepositorySourceDefinition<? extends ModeShapeConfiguration>> repositorySources() {
620
621 Set<String> names = getNamesOfComponentsUnder(ModeShapeLexicon.SOURCES);
622 names.addAll(this.repositorySourceDefinitions.keySet());
623 Set<RepositorySourceDefinition<? extends ModeShapeConfiguration>> results = new HashSet<RepositorySourceDefinition<? extends ModeShapeConfiguration>>();
624 for (String name : names) {
625 results.add(repositorySource(name));
626 }
627 return Collections.unmodifiableSet(results);
628 }
629
630
631
632
633
634
635 public Set<SequencerDefinition<? extends ModeShapeConfiguration>> sequencers() {
636
637 Set<String> names = getNamesOfComponentsUnder(ModeShapeLexicon.SEQUENCERS);
638 names.addAll(this.sequencerDefinitions.keySet());
639 Set<SequencerDefinition<? extends ModeShapeConfiguration>> results = new HashSet<SequencerDefinition<? extends ModeShapeConfiguration>>();
640 for (String name : names) {
641 results.add(sequencer(name));
642 }
643 return Collections.unmodifiableSet(results);
644 }
645
646
647
648
649
650
651
652
653 public MimeTypeDetectorDefinition<? extends ModeShapeConfiguration> mimeTypeDetector( String name ) {
654 return mimeTypeDetectorDefinition(this, name);
655 }
656
657
658
659
660
661
662
663
664 public RepositorySourceDefinition<? extends ModeShapeConfiguration> repositorySource( String name ) {
665 return repositorySourceDefinition(this, name);
666 }
667
668
669
670
671
672
673
674
675 public SequencerDefinition<? extends ModeShapeConfiguration> sequencer( String name ) {
676 return sequencerDefinition(this, name);
677 }
678
679
680
681
682
683
684 public ModeShapeConfiguration and() {
685 return this;
686 }
687
688
689
690
691
692
693
694 public ModeShapeEngine build() {
695 save();
696 return new ModeShapeEngine(getExecutionContextForEngine(), getConfigurationDefinition());
697 }
698
699
700
701
702
703
704
705
706
707
708
709
710 protected ExecutionContext getExecutionContextForEngine() {
711 return new DnaExecutionContext(getExecutionContext());
712 }
713
714
715
716
717
718
719 public interface Returnable<ReturnType> {
720
721
722
723
724
725 ReturnType and();
726 }
727
728
729
730
731
732
733 public interface Removable<ReturnType> {
734
735
736
737
738
739 ReturnType remove();
740 }
741
742
743
744
745
746
747 public interface SetDescription<ReturnType> {
748
749
750
751
752
753
754 ReturnType setDescription( String description );
755
756
757
758
759
760
761 String getDescription();
762 }
763
764
765
766
767
768
769
770 public interface SetProperties<ReturnType> {
771
772
773
774
775
776
777
778 ReturnType setProperty( String beanPropertyName,
779 int value );
780
781
782
783
784
785
786
787
788 ReturnType setProperty( String beanPropertyName,
789 long value );
790
791
792
793
794
795
796
797
798 ReturnType setProperty( String beanPropertyName,
799 short value );
800
801
802
803
804
805
806
807
808 ReturnType setProperty( String beanPropertyName,
809 boolean value );
810
811
812
813
814
815
816
817
818 ReturnType setProperty( String beanPropertyName,
819 float value );
820
821
822
823
824
825
826
827
828 ReturnType setProperty( String beanPropertyName,
829 double value );
830
831
832
833
834
835
836
837
838 ReturnType setProperty( String beanPropertyName,
839 String value );
840
841
842
843
844
845
846
847
848
849 ReturnType setProperty( String beanPropertyName,
850 String value,
851 String... additionalValues );
852
853
854
855
856
857
858
859
860 ReturnType setProperty( String beanPropertyName,
861 Object value );
862
863
864
865
866
867
868
869
870 ReturnType setProperty( String beanPropertyName,
871 Object[] values );
872
873
874
875
876
877
878
879 Property getProperty( String beanPropertyName );
880 }
881
882
883
884
885
886
887
888 public interface ChooseClass<ComponentClassType, ReturnType> {
889
890
891
892
893
894
895
896
897
898 LoadedFrom<ReturnType> usingClass( String classname );
899
900
901
902
903
904
905
906
907
908
909 ReturnType usingClass( Class<? extends ComponentClassType> clazz );
910 }
911
912
913
914
915
916
917 public interface LoadedFrom<ReturnType> {
918
919
920
921
922
923
924
925
926
927
928
929 ReturnType loadedFrom( String... classPathNames );
930
931
932
933
934
935
936
937
938
939 ReturnType loadedFromClasspath();
940 }
941
942
943
944
945 public interface HasName {
946
947
948
949
950
951 String getName();
952 }
953
954
955
956
957
958
959 public interface MimeTypeDetectorDefinition<ReturnType>
960 extends Returnable<ReturnType>, SetDescription<MimeTypeDetectorDefinition<ReturnType>>,
961 SetProperties<MimeTypeDetectorDefinition<ReturnType>>,
962 ChooseClass<MimeTypeDetector, MimeTypeDetectorDefinition<ReturnType>>, Removable<ReturnType> {
963 }
964
965
966
967
968
969
970 public interface RepositorySourceDefinition<ReturnType>
971 extends Returnable<ReturnType>, SetDescription<RepositorySourceDefinition<ReturnType>>,
972 SetProperties<RepositorySourceDefinition<ReturnType>>,
973 ChooseClass<RepositorySource, RepositorySourceDefinition<ReturnType>>, Removable<ReturnType>, HasName {
974
975
976
977
978
979
980
981
982
983 RepositorySourceDefinition<ReturnType> setRetryLimit( int retryLimit );
984 }
985
986
987
988
989
990
991 public interface SequencerDefinition<ReturnType>
992 extends Returnable<ReturnType>, SetDescription<SequencerDefinition<ReturnType>>,
993 SetProperties<SequencerDefinition<ReturnType>>, ChooseClass<StreamSequencer, SequencerDefinition<ReturnType>>,
994 Removable<ReturnType> {
995
996
997
998
999
1000
1001
1002
1003
1004 PathExpressionOutput<ReturnType> sequencingFrom( String inputPathExpression );
1005
1006
1007
1008
1009
1010
1011
1012
1013 SequencerDefinition<ReturnType> sequencingFrom( PathExpression inputPathExpression );
1014
1015
1016
1017
1018
1019
1020 Set<PathExpression> getPathExpressions();
1021 }
1022
1023
1024
1025
1026
1027
1028
1029 public interface PathExpressionOutput<ReturnType> {
1030
1031
1032
1033
1034
1035
1036
1037 SequencerDefinition<ReturnType> andOutputtingTo( String outputExpression );
1038 }
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048 @SuppressWarnings( "unchecked" )
1049 protected <ReturnType extends ModeShapeConfiguration> MimeTypeDetectorDefinition<ReturnType> mimeTypeDetectorDefinition( ReturnType returnObject,
1050 String name ) {
1051 MimeTypeDetectorDefinition<ReturnType> definition = (MimeTypeDetectorDefinition<ReturnType>)mimeTypeDetectorDefinitions.get(name);
1052 if (definition == null) {
1053 definition = new MimeTypeDetectorBuilder<ReturnType>(returnObject, changes(), path(),
1054 ModeShapeLexicon.MIME_TYPE_DETECTORS, name(name));
1055 mimeTypeDetectorDefinitions.put(name, definition);
1056 }
1057 return definition;
1058 }
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068 @SuppressWarnings( "unchecked" )
1069 protected <ReturnType extends ModeShapeConfiguration> RepositorySourceDefinition<ReturnType> repositorySourceDefinition( ReturnType returnObject,
1070 String name ) {
1071 RepositorySourceDefinition<ReturnType> definition = (RepositorySourceDefinition<ReturnType>)repositorySourceDefinitions.get(name);
1072 if (definition == null) {
1073 definition = new SourceBuilder<ReturnType>(returnObject, changes(), path(), ModeShapeLexicon.SOURCES, name(name));
1074 repositorySourceDefinitions.put(name, definition);
1075 }
1076 return definition;
1077 }
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087 @SuppressWarnings( "unchecked" )
1088 protected <ReturnType extends ModeShapeConfiguration> SequencerDefinition<ReturnType> sequencerDefinition( ReturnType returnObject,
1089 String name ) {
1090 SequencerDefinition<ReturnType> definition = (SequencerDefinition<ReturnType>)sequencerDefinitions.get(name);
1091 if (definition == null) {
1092 definition = new SequencerBuilder<ReturnType>(returnObject, changes(), path(), ModeShapeLexicon.SEQUENCERS,
1093 name(name));
1094 sequencerDefinitions.put(name, definition);
1095 }
1096 return definition;
1097 }
1098
1099 protected static class BaseReturnable<ReturnType> implements Returnable<ReturnType> {
1100 protected final ReturnType returnObject;
1101
1102 protected BaseReturnable( ReturnType returnObject ) {
1103 this.returnObject = returnObject;
1104 }
1105
1106
1107
1108
1109
1110
1111 public ReturnType and() {
1112 return returnObject;
1113 }
1114 }
1115
1116
1117
1118
1119
1120
1121
1122 protected static abstract class GraphReturnable<ReturnType, ThisType> extends BaseReturnable<ReturnType>
1123 implements SetDescription<ThisType>, SetProperties<ThisType>, Removable<ReturnType> {
1124 protected final ExecutionContext context;
1125 protected final Graph.Batch batch;
1126 protected final Path path;
1127 private Map<Name, Property> properties = new HashMap<Name, Property>();
1128
1129 protected GraphReturnable( ReturnType returnObject,
1130 Graph.Batch batch,
1131 Path path,
1132 Name... names ) {
1133 super(returnObject);
1134 assert batch != null;
1135 assert path != null;
1136 assert names.length > 0;
1137 this.context = batch.getGraph().getContext();
1138 this.batch = batch;
1139
1140 createIfMissing(path, names).and();
1141 this.path = context.getValueFactories().getPathFactory().create(path, names);
1142 try {
1143 properties = batch.getGraph().getPropertiesByName().on(this.path);
1144 } catch (PathNotFoundException e) {
1145
1146 properties = new HashMap<Name, Property>();
1147 }
1148 }
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158 protected Graph.Create<Graph.Batch> createIfMissing( Name child,
1159 String... segments ) {
1160 Path nodePath = context.getValueFactories().getPathFactory().create(path, child);
1161 Graph.Create<Graph.Batch> result = batch.create(nodePath).orUpdate();
1162 for (String name : segments) {
1163 result.and();
1164 nodePath = context.getValueFactories().getPathFactory().create(nodePath, name);
1165 result = batch.create(nodePath).orUpdate();
1166 }
1167 return result;
1168 }
1169
1170
1171
1172
1173
1174
1175
1176
1177 protected Graph.Create<Graph.Batch> createIfMissing( Name segment ) {
1178 Path nodePath = context.getValueFactories().getPathFactory().create(path, segment);
1179 Graph.Create<Graph.Batch> result = batch.create(nodePath).orUpdate();
1180 return result;
1181 }
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191 protected Graph.Create<Graph.Batch> createIfMissing( Path path,
1192 Name... segments ) {
1193 Path nodePath = path;
1194 Graph.Create<Graph.Batch> result = null;
1195 for (Name name : segments) {
1196 if (result != null) result.and();
1197 nodePath = context.getValueFactories().getPathFactory().create(nodePath, name);
1198 result = batch.create(nodePath).orUpdate();
1199 }
1200 return result;
1201 }
1202
1203 protected Path subpath( Name... segments ) {
1204 return context.getValueFactories().getPathFactory().create(path, segments);
1205 }
1206
1207 protected abstract ThisType thisType();
1208
1209 public String getName() {
1210 return path.getLastSegment().getName().getString(context.getNamespaceRegistry());
1211 }
1212
1213 public ThisType setDescription( String description ) {
1214 return setProperty(ModeShapeLexicon.DESCRIPTION, description);
1215 }
1216
1217 public String getDescription() {
1218 Property property = getProperty(ModeShapeLexicon.DESCRIPTION);
1219 if (property != null && !property.isEmpty()) {
1220 return context.getValueFactories().getStringFactory().create(property.getFirstValue());
1221 }
1222 return null;
1223 }
1224
1225 protected ThisType setProperty( Name propertyName,
1226 Object value ) {
1227
1228 batch.set(propertyName).on(path).to(value).and();
1229
1230 properties.put(propertyName, context.getPropertyFactory().create(propertyName, value));
1231 return thisType();
1232 }
1233
1234 public ThisType setProperty( String propertyName,
1235 Object value ) {
1236 return setProperty(context.getValueFactories().getNameFactory().create(propertyName), value);
1237 }
1238
1239 public ThisType setProperty( Name propertyName,
1240 Object[] values ) {
1241
1242 batch.set(propertyName).on(path).to(values).and();
1243
1244 properties.put(propertyName, context.getPropertyFactory().create(propertyName, values));
1245 return thisType();
1246 }
1247
1248 public ThisType setProperty( String propertyName,
1249 Object[] values ) {
1250 return setProperty(context.getValueFactories().getNameFactory().create(propertyName), values);
1251 }
1252
1253 public ThisType setProperty( String beanPropertyName,
1254 boolean value ) {
1255 return setProperty(beanPropertyName, (Object)value);
1256 }
1257
1258 public ThisType setProperty( String beanPropertyName,
1259 int value ) {
1260 return setProperty(beanPropertyName, (Object)value);
1261 }
1262
1263 public ThisType setProperty( String beanPropertyName,
1264 short value ) {
1265 return setProperty(beanPropertyName, (Object)value);
1266 }
1267
1268 public ThisType setProperty( String beanPropertyName,
1269 long value ) {
1270 return setProperty(beanPropertyName, (Object)value);
1271 }
1272
1273 public ThisType setProperty( String beanPropertyName,
1274 double value ) {
1275 return setProperty(beanPropertyName, (Object)value);
1276 }
1277
1278 public ThisType setProperty( String beanPropertyName,
1279 float value ) {
1280 return setProperty(beanPropertyName, (Object)value);
1281 }
1282
1283 public ThisType setProperty( String beanPropertyName,
1284 String value ) {
1285 return setProperty(beanPropertyName, (Object)value);
1286 }
1287
1288 public ThisType setProperty( String beanPropertyName,
1289 String firstValue,
1290 String... additionalValues ) {
1291 Object[] values = new Object[1 + additionalValues.length];
1292 values[0] = firstValue;
1293 System.arraycopy(additionalValues, 0, values, 1, additionalValues.length);
1294 return setProperty(beanPropertyName, values);
1295 }
1296
1297 public Property getProperty( String beanPropertyName ) {
1298 return properties.get(context.getValueFactories().getNameFactory().create(beanPropertyName));
1299 }
1300
1301 public Property getProperty( Name beanPropertyName ) {
1302 return properties.get(beanPropertyName);
1303 }
1304
1305 public ReturnType remove() {
1306 batch.delete(path);
1307 properties.clear();
1308 return and();
1309 }
1310 }
1311
1312
1313
1314
1315
1316
1317
1318
1319 protected static abstract class GraphComponentBuilder<ReturnType, ThisType, ComponentType>
1320 extends GraphReturnable<ReturnType, ThisType> implements ChooseClass<ComponentType, ThisType> {
1321 protected GraphComponentBuilder( ReturnType returnObject,
1322 Graph.Batch batch,
1323 Path path,
1324 Name... names ) {
1325 super(returnObject, batch, path, names);
1326 }
1327
1328 public LoadedFrom<ThisType> usingClass( final String classname ) {
1329 return new LoadedFrom<ThisType>() {
1330 public ThisType loadedFromClasspath() {
1331 return setProperty(ModeShapeLexicon.CLASSNAME, classname);
1332 }
1333
1334 public ThisType loadedFrom( String... classpath ) {
1335 List<String> classpaths = new ArrayList<String>();
1336
1337 for (String value : classpath) {
1338 if (value == null) continue;
1339 value = value.trim();
1340 if (value.length() == 0) continue;
1341 if (!classpaths.contains(value)) classpaths.add(value);
1342 }
1343 if (classpaths.size() != 0) {
1344 classpath = classpaths.toArray(new String[classpaths.size()]);
1345 setProperty(ModeShapeLexicon.CLASSPATH, classpath);
1346 }
1347 return setProperty(ModeShapeLexicon.CLASSNAME, classname);
1348 }
1349 };
1350 }
1351
1352 public ThisType usingClass( Class<? extends ComponentType> componentClass ) {
1353 return setProperty(ModeShapeLexicon.CLASSNAME, componentClass.getCanonicalName());
1354 }
1355 }
1356
1357 protected static class MimeTypeDetectorBuilder<ReturnType>
1358 extends GraphComponentBuilder<ReturnType, MimeTypeDetectorDefinition<ReturnType>, MimeTypeDetector>
1359 implements MimeTypeDetectorDefinition<ReturnType> {
1360 protected MimeTypeDetectorBuilder( ReturnType returnObject,
1361 Graph.Batch batch,
1362 Path path,
1363 Name... names ) {
1364 super(returnObject, batch, path, names);
1365 }
1366
1367 @Override
1368 protected MimeTypeDetectorBuilder<ReturnType> thisType() {
1369 return this;
1370 }
1371
1372 }
1373
1374 protected static class SourceBuilder<ReturnType>
1375 extends GraphComponentBuilder<ReturnType, RepositorySourceDefinition<ReturnType>, RepositorySource>
1376 implements RepositorySourceDefinition<ReturnType> {
1377 protected SourceBuilder( ReturnType returnObject,
1378 Graph.Batch batch,
1379 Path path,
1380 Name... names ) {
1381 super(returnObject, batch, path, names);
1382 }
1383
1384 @Override
1385 protected RepositorySourceDefinition<ReturnType> thisType() {
1386 return this;
1387 }
1388
1389 public RepositorySourceDefinition<ReturnType> setRetryLimit( int retryLimit ) {
1390 return setProperty(ModeShapeLexicon.RETRY_LIMIT, retryLimit);
1391 }
1392
1393 @Override
1394 public RepositorySourceDefinition<ReturnType> setProperty( String propertyName,
1395 Object value ) {
1396 Name name = context.getValueFactories().getNameFactory().create(propertyName);
1397
1398 if (name.getLocalName().equals(ModeShapeLexicon.RETRY_LIMIT.getLocalName())) name = ModeShapeLexicon.RETRY_LIMIT;
1399 if (name.getLocalName().equals(ModeShapeLexicon.DESCRIPTION.getLocalName())) name = ModeShapeLexicon.DESCRIPTION;
1400 return super.setProperty(name, value);
1401 }
1402
1403 @Override
1404 public Property getProperty( Name name ) {
1405
1406 if (name.getLocalName().equals(ModeShapeLexicon.RETRY_LIMIT.getLocalName())) name = ModeShapeLexicon.RETRY_LIMIT;
1407 if (name.getLocalName().equals(ModeShapeLexicon.DESCRIPTION.getLocalName())) name = ModeShapeLexicon.DESCRIPTION;
1408 return super.getProperty(name);
1409 }
1410 }
1411
1412 protected static class SequencerBuilder<ReturnType>
1413 extends GraphComponentBuilder<ReturnType, SequencerDefinition<ReturnType>, StreamSequencer>
1414 implements SequencerDefinition<ReturnType> {
1415
1416 protected SequencerBuilder( ReturnType returnObject,
1417 Graph.Batch batch,
1418 Path path,
1419 Name... names ) {
1420 super(returnObject, batch, path, names);
1421 }
1422
1423 @Override
1424 protected SequencerDefinition<ReturnType> thisType() {
1425 return this;
1426 }
1427
1428 public Set<PathExpression> getPathExpressions() {
1429 Set<PathExpression> expressions = new HashSet<PathExpression>();
1430 try {
1431 Property existingExpressions = getProperty(ModeShapeLexicon.PATH_EXPRESSION);
1432 if (existingExpressions != null) {
1433 for (Object existing : existingExpressions.getValuesAsArray()) {
1434 String existingExpression = context.getValueFactories().getStringFactory().create(existing);
1435 expressions.add(PathExpression.compile(existingExpression));
1436 }
1437 }
1438 } catch (PathNotFoundException e) {
1439
1440 }
1441 return expressions;
1442 }
1443
1444 public SequencerDefinition<ReturnType> sequencingFrom( PathExpression expression ) {
1445 CheckArg.isNotNull(expression, "expression");
1446 Set<PathExpression> compiledExpressions = getPathExpressions();
1447 compiledExpressions.add(expression);
1448 String[] strings = new String[compiledExpressions.size()];
1449 int index = 0;
1450 for (PathExpression compiledExpression : compiledExpressions) {
1451 strings[index++] = compiledExpression.getExpression();
1452 }
1453 setProperty(ModeShapeLexicon.PATH_EXPRESSION, strings);
1454 return this;
1455 }
1456
1457 public PathExpressionOutput<ReturnType> sequencingFrom( final String fromPathExpression ) {
1458 CheckArg.isNotEmpty(fromPathExpression, "fromPathExpression");
1459 return new PathExpressionOutput<ReturnType>() {
1460 public SequencerDefinition<ReturnType> andOutputtingTo( String into ) {
1461 CheckArg.isNotEmpty(into, "into");
1462 return sequencingFrom(PathExpression.compile(fromPathExpression + " => " + into));
1463 }
1464 };
1465 }
1466 }
1467
1468
1469
1470
1471 @Immutable
1472 public static class ConfigurationDefinition {
1473 private final String name;
1474 private final ClassLoaderFactory classLoaderFactory;
1475 private final RepositorySource source;
1476 private final Path path;
1477 private final String workspace;
1478 private final ExecutionContext context;
1479 private Graph graph;
1480
1481 protected ConfigurationDefinition( String configurationName,
1482 RepositorySource source,
1483 String workspace,
1484 Path path,
1485 ExecutionContext context,
1486 ClassLoaderFactory classLoaderFactory ) {
1487 assert configurationName != null;
1488 this.name = configurationName;
1489 this.source = source;
1490 this.path = path != null ? path : RootPath.INSTANCE;
1491 this.workspace = workspace;
1492 this.context = context;
1493 this.classLoaderFactory = classLoaderFactory != null ? classLoaderFactory : new StandardClassLoaderFactory();
1494 }
1495
1496
1497
1498
1499
1500
1501 public String getName() {
1502 return name;
1503 }
1504
1505
1506
1507
1508
1509
1510 public RepositorySource getRepositorySource() {
1511 return source;
1512 }
1513
1514
1515
1516
1517
1518
1519 public Path getPath() {
1520 return path;
1521 }
1522
1523
1524
1525
1526
1527
1528 public String getWorkspace() {
1529 return workspace;
1530 }
1531
1532
1533
1534
1535 public ExecutionContext getContext() {
1536 return context;
1537 }
1538
1539
1540
1541
1542 public ClassLoaderFactory getClassLoaderFactory() {
1543 return classLoaderFactory;
1544 }
1545
1546
1547
1548
1549
1550
1551
1552 public ConfigurationDefinition with( String name ) {
1553 if (name == null) name = this.name;
1554 return new ConfigurationDefinition(name, source, workspace, path, context, classLoaderFactory);
1555 }
1556
1557
1558
1559
1560
1561
1562
1563 public ConfigurationDefinition with( Path path ) {
1564 return new ConfigurationDefinition(name, source, workspace, path, context, classLoaderFactory);
1565 }
1566
1567
1568
1569
1570
1571
1572
1573
1574 public ConfigurationDefinition withWorkspace( String workspace ) {
1575 return new ConfigurationDefinition(name, source, workspace, path, context, classLoaderFactory);
1576 }
1577
1578
1579
1580
1581
1582
1583
1584
1585 public ConfigurationDefinition with( ClassLoaderFactory classLoaderFactory ) {
1586 return new ConfigurationDefinition(name, source, workspace, path, context, classLoaderFactory);
1587 }
1588
1589
1590
1591
1592
1593
1594 public Graph graph() {
1595 if (graph == null) {
1596 graph = Graph.create(source, context);
1597 if (workspace != null) graph.useWorkspace(workspace);
1598 }
1599 return graph;
1600 }
1601 }
1602 }