2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.io
.common
;
12 import java
.util
.ArrayList
;
13 import java
.util
.Iterator
;
14 import java
.util
.LinkedList
;
15 import java
.util
.List
;
17 import org
.apache
.log4j
.Logger
;
18 import org
.springframework
.transaction
.TransactionStatus
;
20 import eu
.etaxonomy
.cdm
.api
.application
.ICdmRepository
;
21 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
22 import eu
.etaxonomy
.cdm
.common
.monitor
.SubProgressMonitor
;
23 import eu
.etaxonomy
.cdm
.filter
.TaxonNodeFilter
;
24 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
30 public class TaxonNodeOutStreamPartitioner
<STATE
extends IoStateBase
> {
32 private static final Logger logger
= Logger
.getLogger(TaxonNodeOutStreamPartitioner
.class);
34 //************************* STATIC ***************************************************/
36 public static <ST
extends XmlExportState
> TaxonNodeOutStreamPartitioner
NewInstance(
37 ICdmRepository repository
, IoStateBase state
,
38 TaxonNodeFilter filter
, Integer partitionSize
,
39 IProgressMonitor parentMonitor
, Integer parentTicks
){
40 TaxonNodeOutStreamPartitioner
<ST
> taxonNodePartitioner
41 = new TaxonNodeOutStreamPartitioner(repository
, state
, filter
, partitionSize
,
42 parentMonitor
, parentTicks
);
43 return taxonNodePartitioner
;
46 //*********************** VARIABLES *************************************************/
50 * counter for the partitions
52 private int currentPartition
;
54 private TransactionStatus txStatus
;
56 private boolean readOnly
= true;
60 private final ICdmRepository repository
;
62 private final TaxonNodeFilter filter
;
67 * Number of records handled in the partition
69 private final int partitionSize
;
71 private int totalCount
= -1;
72 private List
<Integer
> idList
;
74 private IProgressMonitor parentMonitor
;
75 private Integer parentTicks
;
77 private SubProgressMonitor monitor
;
79 private LinkedList
<TaxonNode
> fifo
= new LinkedList
<>();
81 private Iterator
<Integer
> idIterator
;
83 private int currentIndex
;
85 private static final int retrieveFactor
= 1;
86 private static final int iterateFactor
= 2;
89 //*********************** CONSTRUCTOR *************************************************/
91 private TaxonNodeOutStreamPartitioner(ICdmRepository repository
, STATE state
,
92 TaxonNodeFilter filter
, Integer partitionSize
,
93 IProgressMonitor parentMonitor
, Integer parentTicks
){
94 this.repository
= repository
;
96 this.partitionSize
= partitionSize
;
98 this.parentMonitor
= parentMonitor
;
99 this.parentTicks
= parentTicks
;
102 //************************ METHODS ****************************************************/
104 public void initialize(){
107 parentMonitor
.subTask("Compute total number of records");
108 totalCount
= ((Long
)repository
.getTaxonNodeService().count(filter
)).intValue();
109 idList
= repository
.getTaxonNodeService().idList(filter
);
110 int parTicks
= this.parentTicks
== null? totalCount
: this.parentTicks
;
112 monitor
= SubProgressMonitor
.NewStarted(parentMonitor
, parTicks
,
113 "Taxon node streamer", totalCount
* (retrieveFactor
+ iterateFactor
));
114 idIterator
= idList
.iterator();
115 monitor
.subTask("id iterator created");
119 public TaxonNode
next(){
120 int currentIndexAtStart
= currentIndex
;
123 List
<TaxonNode
> list
= getNextPartition();
126 if (!fifo
.isEmpty()){
127 TaxonNode result
= fifo
.removeFirst();
128 // worked should be called after each step is ready,
129 //this is usually after each next() call but not for the first
130 if (currentIndexAtStart
> 0){
131 monitor
.worked(iterateFactor
);
145 private List
<TaxonNode
> getNextPartition() {
146 List
<Integer
> partList
= new ArrayList
<>();
148 if (txStatus
!= null){
151 txStatus
= startTransaction();
153 txStatus
.setRollbackOnly();
155 while (partList
.size() < partitionSize
&& idIterator
.hasNext()){
156 partList
.add(idIterator
.next());
159 List
<TaxonNode
> partition
= new ArrayList
<>();
160 if (!partList
.isEmpty()){
161 monitor
.subTask(String
.format("Reading partition %d/%d", currentPartition
+ 1, (totalCount
/ partitionSize
) +1 ));
162 List
<String
> propertyPaths
= new ArrayList
<String
>();
163 propertyPaths
.add("taxon");
164 propertyPaths
.add("taxon.name");
165 partition
= repository
.getTaxonNodeService().loadByIds(partList
, propertyPaths
);
166 monitor
.worked(partition
.size());
168 monitor
.subTask(String
.format("Writing partition %d/%d", currentPartition
, (totalCount
/ partitionSize
) +1 ));
173 private void commitTransaction() {
174 if (!txStatus
.isCompleted()){
176 repository
.rollback(txStatus
);
178 repository
.commitTransaction(txStatus
);
183 private TransactionStatus
startTransaction() {
184 return repository
.startTransaction(readOnly
);