1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.store

File ProvidingTransactionRunnable.java

 

Coverage histogram

../../../img/srcFileCovDistChart5.png
74% of files have more coverage

Code metrics

0
2
2
1
131
12
2
1
1
2
1

Classes

Class Line # Actions
ProvidingTransactionRunnable 104 2 0% 2 2
0.550%
 

Contributing tests

This file is covered by 2 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.store;
21   
22    /**
23    * A special type of TransactionRunnable which guarentees to provide state to the TransactionRunnables
24    * which are run inside of it. It can also provide them with data.
25    * Suppose you have a unit of work which loads data and that data must be saved in a later
26    * TransactionRunnable in the same transaction.
27    *
28    * IE:
29    * TR1 fetch data A1
30    * TR2 update another data A2
31    * TR3 perform some operation involving A1
32    *
33    * A TR3 can only run inside of a TR1.
34    * To make things interesting we will assume that TR1, TR2, and TR3 all must run inside of a database
35    * transaction.
36    * TR1 is interesting because it <i>requires</i> a database transaction and it <i>provides</i> some data
37    * (data A1).
38    *
39    * To implement this safely, TR1 should be a ProvidingTransactionRunnable.
40    * We will assume that there already exists a TransactionRunnable for handling the begin and commit of the
41    * database transaction, this will be called: DBStartableTransactionRunnable and we will assume that it
42    * <i>provides</i> an interface called DBTransaction so TR1, TR2, and TR3 will all <i>require</i>
43    * DBTransaction.
44    *
45    * <pre><code>
46    * // MyInterfaceWithDataA1 must extend DBTransaction because all
47    * // ProvidingTransactionRunnables must provide more than they require.
48    * public interface MyInterfaceWithDataA1 extends DBTransaction { Data getA1(); }
49    *
50    * public class ImplementationWithDataA1 implements MyInterfaceWithDataA1 { ... }
51    *
52    * public class TR1 extends ProvidingTransactionRunnable&lt;DBTransaction, MyInterfaceWithDataA1&gt;
53    * {
54    * private Data dataA1;
55    *
56    * protected void onRun() { this.dataA1 = ..... }
57    *
58    * {@literal @}Override
59    * protected MyInterfaceWithDataA1 getProvidedContext()
60    * {
61    * // this.getContext() will return a DBTransaction which our implementation can wrap.
62    * return new ImplementationWithDataA1(this.getContext(), this.dataA1);
63    * }
64    * }
65    *
66    * public class TR2 extends TransactionRunnable&lt;DBTransaction&gt; { ... }
67    *
68    * public class TR3 extends TransactionRunnable&lt;MyInterfaceWithDataA1&gt;
69    * {
70    * protected void onRun()
71    * {
72    * final Data A1 = this.getContext();
73    * ...
74    * }
75    * }
76    *
77    * To use these classes:
78    *
79    * DBStartableTransactionRunnable run = new DBStartableTransactionRunnable(dataSourceName);
80    * TransactionRunnable&lt;MyInterfaceWithDataA1&gt; tr1 = new TR1();
81    * tr1.runIn(run);
82    * TransactionRunnable&lt;DBTransaction&gt; tr2 = new TR2();
83    * TransactionRunnable&lt;MyInterfaceWithDataA1&gt; tr2WithNewCapabilities = tr2.runIn(tr1.asProvider());
84    * new TR3().runIn(tr2WithNewCapabilities);
85    * // This would fail at compile time: new TR3().runIn(tr2);
86    * run.start();
87    * </code></pre>
88    *
89    * @param <R> The type of transaction or transaction state which this runnable requires.
90    * A TransactionRunnable which alters a database through Hibernate would fail if it was
91    * started outside of a TransactionRunnable which began and committed a transaction around
92    * it. A class which extends {@code TransactionRunnable<DatabaseTransaction>} can only be
93    * run inside of another {@code TransactionRunnable<DatabaseTransaction>} or inside of a
94    * {@code ProvidingTransactionRunnable<?, DatabaseTransaction>}
95    * Breaking that rule will be a compile time error.
96    *
97    * @param <P> the transaction state which this TransactionRunnable provides. Any
98    * {@code TransactionRunnable<P>} may be {@link TransactionRunnable#runIn(TransactionRunnable)}
99    * This runnable.
100    *
101    * @version $Id: d1b3ee449ee98c6d4aa70f4995940aa8a20b0a6f $
102    * @since 3.0M2
103    */
 
104    public class ProvidingTransactionRunnable<R, P extends R> extends TransactionRunnable<R>
105    {
106    /**
107    * Get whatever is provided by this ProvidingTransactionRunnable.
108    *
109    * @return an implementation of P, the transaction type which this runnable runs in.
110    * null by default.
111    * @see TransactionRunnable#getContext()
112    */
 
113  0 toggle protected P getProvidedContext()
114    {
115  0 return null;
116    }
117   
118    /**
119    * View this as what it provides.
120    * Cast this ProvidingTransactionRunnable to the type of
121    * TransactionRunnable which can run inside of it.
122    *
123    * @return this ProvidingTransactionRunnable cast to a TransactionRunnable<P>
124    */
 
125  2 toggle public TransactionRunnable<P> asProvider()
126    {
127    // This cast is ok because every PTR<R, P> promises to provide P.
128    // calling runIn on the output from this cast is also safe because P extends R.
129  2 return (TransactionRunnable<P>) this;
130    }
131    }