extended controller to enable feature export
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / csv / redlist / demo / CsvDemoExport.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
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.
8 */
9
10 package eu.etaxonomy.cdm.io.csv.redlist.demo;
11
12 import java.io.FileNotFoundException;
13 import java.io.PrintWriter;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.Comparator;
17 import java.util.HashSet;
18 import java.util.List;
19 import java.util.Set;
20 import java.util.UUID;
21
22 import org.apache.commons.lang.StringUtils;
23 import org.apache.log4j.Logger;
24 import org.springframework.stereotype.Component;
25 import org.springframework.transaction.TransactionStatus;
26
27 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
28 import eu.etaxonomy.cdm.model.common.CdmBase;
29 import eu.etaxonomy.cdm.model.common.IdentifiableSource;
30 import eu.etaxonomy.cdm.model.common.Language;
31 import eu.etaxonomy.cdm.model.common.RelationshipTermBase;
32 import eu.etaxonomy.cdm.model.description.CategoricalData;
33 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
34 import eu.etaxonomy.cdm.model.description.Distribution;
35 import eu.etaxonomy.cdm.model.description.Feature;
36 import eu.etaxonomy.cdm.model.description.State;
37 import eu.etaxonomy.cdm.model.description.TaxonDescription;
38 import eu.etaxonomy.cdm.model.description.TextData;
39 import eu.etaxonomy.cdm.model.location.NamedArea;
40 import eu.etaxonomy.cdm.model.name.NonViralName;
41 import eu.etaxonomy.cdm.model.reference.Reference;
42 import eu.etaxonomy.cdm.model.taxon.Classification;
43 import eu.etaxonomy.cdm.model.taxon.Synonym;
44 import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
45 import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
46 import eu.etaxonomy.cdm.model.taxon.Taxon;
47 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
48 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
49 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
50 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
51
52
53 /**
54 * @author a.oppermann
55 * @created 18.10.2012
56 */
57
58 @Component
59 public class CsvDemoExport extends CsvDemoBase {
60 private static final Logger logger = Logger.getLogger(CsvDemoExport.class);
61
62 private static final String ROW_TYPE = "http://rs.tdwg.org/dwc/terms/Taxon";
63 private static final String fileName = "RedlistCoreTax.csv";
64
65 public CsvDemoExport() {
66 super();
67 this.ioName = this.getClass().getSimpleName();
68 }
69
70
71 /** Retrieves data from a CDM DB and serializes them CDM to CSV.
72 * Starts with root taxa and traverses the classification to retrieve
73 * children taxa, synonyms, relationships, descriptive data, red list
74 * status (features).
75 * Taxa that are not part of the classification are not found.
76 *
77 * @param exImpConfig
78 * @param dbname
79 * @param filename
80 */
81 @Override
82 protected void doInvoke(CsvDemoExportState state){
83 CsvDemoExportConfigurator config = state.getConfig();
84 TransactionStatus txStatus = startTransaction(true);
85
86 List<NamedArea> selectedAreas = config.getNamedAreas();
87 Set<Classification> classificationSet = assembleClassificationSet(config);
88
89 IProgressMonitor progressMonitor = null;
90 if(config.getProgressMonitor() != null) {
91 progressMonitor = config.getProgressMonitor();
92 }
93 PrintWriter writer = null;
94 try {
95 //json/xml result list
96 List<CsvDemoRecord> recordList = null;
97 if(config.getRecordList() != null){
98 recordList = config.getRecordList();
99 performJsonXMLPagination(state, config, txStatus, classificationSet, recordList);
100 }
101
102
103 if(!config.getDestination().isDirectory()){
104 try {
105 writer = new PrintWriter(config.getDestination());
106 performCSVExport(state, config, txStatus, classificationSet, progressMonitor, writer);
107 } catch (FileNotFoundException e) {
108 e.printStackTrace();
109 }
110 }
111 } catch (ClassCastException e) {
112 e.printStackTrace();
113 }
114 finally{
115 if(writer != null){
116 writer.close();
117 }
118 this.clearExistingRecordIds();
119 }
120 // commitTransaction(txStatus);
121 return;
122 }
123
124
125 /**
126 * @param state
127 * @param config
128 * @param txStatus
129 * @param classificationSet
130 * @param recordList
131 */
132 private void performJsonXMLPagination(CsvDemoExportState state, CsvDemoExportConfigurator config,
133 TransactionStatus txStatus, Set<Classification> classificationSet, List<CsvDemoRecord> recordList) {
134 // TODO Auto-generated method stub
135 Classification classification = null;
136 for(Classification c : classificationSet){
137 classification = c;
138 //this sets the total amount of records for pagination
139 config.setTaxonNodeListSize(getTaxonNodeService().countAllNodesForClassification(c));
140 }
141 //calculate pagination
142 int start = config.getPageSize() * config.getPageNumber();
143 List<TaxonNode> result = getTaxonNodeService().listAllNodesForClassification(classification, start, config.getPageSize());
144
145 for (TaxonNode node : result){
146 Taxon taxon = CdmBase.deproxy(node.getTaxon(), Taxon.class);
147 CsvDemoRecord record = assembleRecord(state);
148 NonViralName<?> name = CdmBase.deproxy(taxon.getName(), NonViralName.class);
149 config.setClassificationTitleCache(classification.getTitleCache());
150 if (! this.recordExists(taxon)){
151 handleTaxonBase(record, taxon, name, classification, null, false, false, config, node);
152 recordList.add(record);
153 this.addExistingRecord(taxon);
154 }
155 }
156 commitTransaction(txStatus);
157 }
158
159
160 /**
161 * @param state
162 * @param config
163 * @param txStatus
164 * @param classificationSet
165 * @param progressMonitor
166 * @param writer
167 * @return
168 */
169 private void performCSVExport(CsvDemoExportState state, CsvDemoExportConfigurator config,
170 TransactionStatus txStatus, Set<Classification> classificationSet, IProgressMonitor progressMonitor,
171 PrintWriter writer) {
172 //obtain chuncks of taxonNodes
173 int totalWork = 0;
174 int work = 0;
175 int limit = 500;
176 int end = 500;
177 int start = 0;
178
179 //TODO: Questionable if this information is really necessary, with respect to memory usage
180 Classification classification = null;
181 for(Classification c : classificationSet){
182 classification = c;
183 totalWork = getTaxonNodeService().countAllNodesForClassification(c);
184
185
186 if(progressMonitor != null) {
187 progressMonitor.beginTask("", totalWork);
188 }
189 List<TaxonNode> result = new ArrayList<TaxonNode>();
190 int totalNodes = getTaxonNodeService().count(TaxonNode.class);
191
192 for(int i = 0 ; i < totalNodes; i++){
193
194 //geographical Filter
195 // List<TaxonNode> taxonNodes = handleGeographicalFilter(state, classificationSet, config, limit, start);
196
197 result = getTaxonNodeService().listAllNodesForClassification(classification, start, limit);
198
199 logger.info(result.size());
200
201
202 for (TaxonNode node : result){
203 Taxon taxon = CdmBase.deproxy(node.getTaxon(), Taxon.class);
204 CsvDemoRecord record = assembleRecord(state);
205 NonViralName<?> name = CdmBase.deproxy(taxon.getName(), NonViralName.class);
206 // Classification classification = node.getClassification();
207 config.setClassificationTitleCache(classification.getTitleCache());
208 if (! this.recordExists(taxon)){
209
210 handleTaxonBase(record, taxon, name, classification, null, false, false, config, node);
211 if(config.getDestination() != null){
212 record.write(writer);
213 }
214 this.addExistingRecord(taxon);
215 }
216 //misapplied names
217 //handleMisapplication(taxon, writer, classification, record, config, node);
218
219 if(progressMonitor !=null) {
220 if(work < totalWork-1) {
221 progressMonitor.worked(1);
222 }
223 work++;
224 }
225 }
226 if(writer != null){
227 writer.flush();
228 commitTransaction(txStatus);
229 txStatus = startTransaction(true);
230 }
231 //get next 1000 results
232 if(result.size()%limit == 0){
233 //increase only once to avoid same row
234 if(i==0){
235 start++;
236 }
237 start = start + limit;
238 end = end + limit;
239 result = null;
240 }else{
241 break;
242 }
243 }
244 }
245 }
246
247
248 //TODO: Exception handling
249 /**
250 *
251 * @param config
252 * @return
253 */
254 protected Set<Classification> assembleClassificationSet(CsvDemoExportConfigurator config){
255 if(config != null){
256 Set<UUID> classificationUuidSet = config.getClassificationUuids();
257 List<Classification> classificationList = getClassificationService().find(classificationUuidSet);
258 Set<Classification> classificationSet = new HashSet<Classification>();
259 classificationSet.addAll(classificationList);
260 return classificationSet;
261 }
262 return null;
263 }
264
265 //TODO: Exception handling
266 /**
267 *
268 * @param state
269 * @return
270 */
271 private CsvDemoRecord assembleRecord(CsvDemoExportState state) {
272 if(state!=null){
273 CsvDemoExportConfigurator config = state.getConfig();
274 CsvDemoMetaDataRecord metaRecord = new CsvDemoMetaDataRecord(true, fileName, ROW_TYPE);
275 state.addMetaRecord(metaRecord);
276 CsvDemoRecord record = new CsvDemoRecord(metaRecord, config);
277 return record;
278 }
279 return null;
280 }
281
282 /**
283 * Takes positive List of areas and iterates over a given classification
284 * and their {@link Taxon} to return all {@link Taxon} with the desired
285 * geographical attribute.
286 *
287 * <p><p>
288 *
289 * If selectedAreas is null all {@link TaxonNode}s of the given {@link Classification} will be returned.
290 *
291 * @param selectedAreas
292 * @param classificationSet
293 * @param limit
294 * @param start
295 * @return
296 */
297 // protected List<TaxonNode> handleGeographicalFilter(CsvDemoExportState state,
298 // Set<Classification> classificationSet, CsvDemoExportConfigurator config, int limit, int start) {
299 // List<TaxonNode> filteredNodes = new ArrayList<TaxonNode>();
300 // List<TaxonNode> allNodes = new ArrayList<TaxonNode>();
301 // //Check if json/XML export
302 // if(config.getRecordList() != null){
303 // if(config.getProgressMonitor() != null) {
304 // config.getProgressMonitor().subTask("Calculate size of export...");
305 // }
306 // //FIXME does not filter for classifications
307 // allNodes = getTaxonNodeService().list(TaxonNode.class, config.getPageSize(), config.getPageNumber(), null, null);
308 // config.setTaxonNodeListSize(getAllNodes(classificationSet).size());
309 // //getTaxonNodeService().page(TaxonNode.class, config.getPageSize(), config.getPageNumber(), null, null).getRecords();
310 // }else{
311 //
312 // //do your own pagination
313 // allNodes = getAllNodes(classificationSet);
314 //
315 // }
316 // //Geographical filter
317 // if(state.getConfig().isDoGeographicalFilter()){
318 // List<NamedArea> selectedAreas = state.getConfig().getNamedAreas();
319 // logger.info(selectedAreas.size());
320 // if(selectedAreas != null && !selectedAreas.isEmpty() && selectedAreas.size() < 16){
321 // // if(selectedAreas.size() == 16){
322 // // //Germany TDWG Level 3
323 // // String germany="uu7b7c2db5-aa44-4302-bdec-6556fd74b0b9id";
324 // // selectedAreas.add((NamedArea) getTermService().find(UUID.fromString(germany)));
325 // // }
326 // for (TaxonNode node : allNodes){
327 // Taxon taxon = CdmBase.deproxy(node.getTaxon(), Taxon.class);
328 // Set<TaxonDescription> descriptions = taxon.getDescriptions();
329 // for (TaxonDescription description : descriptions){
330 // for (DescriptionElementBase el : description.getElements()){
331 // if (el.isInstanceOf(Distribution.class) ){
332 // Distribution distribution = CdmBase.deproxy(el, Distribution.class);
333 // NamedArea area = distribution.getArea();
334 // for(NamedArea selectedArea:selectedAreas){
335 // if(selectedArea.getUuid().equals(area.getUuid())){
336 // filteredNodes.add(node);
337 // }
338 // }
339 // }
340 // }
341 // }
342 // }
343 // }else{
344 // filteredNodes = allNodes;
345 // }
346 // }
347 // return filteredNodes;
348 // }
349
350 /**
351 * handles misapplied {@link Taxon}
352 * @param taxon
353 * @param writer
354 * @param classification
355 * @param metaRecord
356 * @param config
357 * @param node
358 */
359 // private void handleMisapplication(Taxon taxon, PrintWriter writer, Classification classification, CsvDemoRecord record, CsvDemoExportConfigurator config, TaxonNode node) {
360 // Set<Taxon> misappliedNames = taxon.getMisappliedNames();
361 // for (Taxon misappliedName : misappliedNames ){
362 //// CsvTaxRecordRedlist record = new CsvTaxRecordRedlist(metaRecord, config);
363 // TaxonRelationshipType relType = TaxonRelationshipType.MISAPPLIED_NAME_FOR();
364 // NonViralName<?> name = CdmBase.deproxy(misappliedName.getName(), NonViralName.class);
365 //
366 // if (! this.recordExists(misappliedName)){
367 // handleTaxonBase(record, misappliedName, name, taxon, classification, relType, false, false, config, node);
368 // if(writer != null){
369 // record.write(writer);
370 // }
371 // this.addExistingRecord(misappliedName);
372 // }
373 // }
374 // }
375
376 /**
377 * handles the information record for the actual {@link Taxon} including {@link Classification classification}, Taxon Name, Taxon ID,
378 * Taxon Status, Synonyms, {@link Feature features} data
379 * @param record the concrete information record
380 * @param taxonBase {@link Taxon}
381 * @param name
382 * @param acceptedTaxon
383 * @param parent
384 * @param basionym
385 * @param isPartial
386 * @param isProParte
387 * @param config
388 * @param node
389 * @param node
390 * @param type
391 */
392 private void handleTaxonBase(CsvDemoRecord record,TaxonBase<?> taxonBase,
393 NonViralName<?> name, Classification classification,
394 RelationshipTermBase<?> relType, boolean isProParte, boolean isPartial,
395 CsvDemoExportConfigurator config, TaxonNode node) {
396
397 Taxon taxon = (Taxon) taxonBase;
398 List<Feature> features = config.getFeatures();
399 if(config.getDestination() != null){
400 record.setHeadLinePrinted(config.isHasHeaderLines());
401 if(config.isRedlistFeatures()){
402 if(features != null){
403 record.setPrintFeatures(features);
404 }
405 }
406 config.setHasHeaderLines(false);
407 }
408 if(config.isClassification()){
409 record.setDatasetName(classification.getTitleCache());
410 }
411 if(config.isTaxonName()){
412 record.setScientificName(name.getNameCache());
413 }
414 if(config.isTaxonNameID()){
415 record.setScientificNameId(name.getUuid().toString());
416 }
417 if(config.isAuthor()){
418 String authorshipCache = name.getAuthorshipCache();
419 if(authorshipCache == null){
420 authorshipCache = "";
421 }
422 record.setAuthorName(authorshipCache);
423 }
424 if(config.isRank()){
425 String rank;
426 if(taxon.getName().getRank() == null){
427 rank = "";
428 }else{
429 rank = taxon.getName().getRank().toString();
430 }
431 record.setRank(rank);
432 }
433 if(config.isTaxonStatus()){
434 handleTaxonomicStatus(record, name, relType, isProParte, isPartial);
435 }
436 if(config.isAcceptedName()){
437 //TODO write routine for accepted Name
438 }
439 if(config.isTaxonConceptID()){
440 UUID taxonUuid = taxonBase.getUuid();
441 if(taxonUuid == null){
442 taxonUuid = UUID.fromString("");
443 }
444 record.setTaxonConceptID(taxonUuid.toString());
445 }
446 if(config.isParentID()){
447 String parentUUID;
448 if(node.getParent().getTaxon() == null){
449 parentUUID = "";
450 }else{
451 parentUUID = node.getParent().getTaxon().getUuid().toString();
452 }
453 record.setParentUUID(parentUUID);
454 }
455 if(config.isLastChange()){
456 String lastChange;
457 if(taxon.getUpdated() == null){
458 lastChange = "";
459 }else{
460 lastChange = taxon.getUpdated().toString();
461 }
462 record.setLastChange(lastChange);
463 }
464 if(config.isSynonyms()){
465 handleSynonyms(record,taxon);
466 }
467 if(config.isDistributions()){
468 handleDiscriptionData(record, taxon);
469 }
470 if(config.isRedlistFeatures()){
471 if(features!= null) {
472
473 List<List<String>> featureCells = new ArrayList<List<String>>(features.size());
474 for(int i = 0; i < features.size(); i++) {
475 featureCells.add(new ArrayList<String>());
476 }
477 handleRelatedRedlistStatus(record, taxon, false, featureCells, features);
478 handleRelatedRedlistStatus(record, taxon, true, featureCells, features);
479
480 }
481 }
482
483 if(config.isExternalID()){
484 Set<IdentifiableSource> sources = taxonBase.getSources();
485 for(IdentifiableSource source:sources){
486 Reference<?> citation = source.getCitation();
487 /*
488 * TODO: handle this more generic.
489 * see ticket #4040
490 *
491 */
492 if(citation.getId() == 22){
493 String idInSource = source.getIdInSource();
494 if(idInSource == null){
495 idInSource = "";
496 }
497 record.setExternalID(idInSource);
498
499 }
500 }
501 }
502 }
503
504 /**
505 * @param record
506 * @param name
507 * @param type
508 * @param isPartial
509 * @param isProParte
510 */
511 private void handleTaxonomicStatus(
512 CsvDemoRecord record,
513 NonViralName<?> name,
514 RelationshipTermBase<?> type,
515 boolean isProParte,
516 boolean isPartial) {
517 if (type == null && name.getNomenclaturalCode()!= null && name.getNomenclaturalCode().acceptedTaxonStatusLabel() != null){
518 String acceptedTaxonStatusLabel = name.getNomenclaturalCode().acceptedTaxonStatusLabel();
519 if(StringUtils.isEmpty(acceptedTaxonStatusLabel)){
520 acceptedTaxonStatusLabel="";
521 }
522 record.setTaxonomicStatus(acceptedTaxonStatusLabel);
523 }else if(name.getNomenclaturalCode() != null && name.getNomenclaturalCode().synonymStatusLabel() != null){
524 String status = name.getNomenclaturalCode().synonymStatusLabel();
525 if (type.equals(SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF())){
526 status = "heterotypicSynonym";
527 }else if(type.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){
528 status = "homotypicSynonym";
529 }else if(type.equals(TaxonRelationshipType.MISAPPLIED_NAME_FOR())){
530 status = "misapplied";
531 }
532 if (isProParte){
533 status = "proParteSynonym";
534 }else if (isPartial){
535 String message = "Partial synonym is not part of the gbif toxonomic status vocabulary";
536 logger.warn(message);
537 status = "partialSynonym";
538 }
539
540 record.setTaxonomicStatus(status);
541 }
542 }
543
544 /**
545 *
546 * This method concatenates several synonyms in a list.
547 *
548 * @param record
549 * @param taxon
550 */
551 private void handleSynonyms(CsvDemoRecord record, Taxon taxon) {
552
553 Set<SynonymRelationship> synRels = taxon.getSynonymRelations();
554 ArrayList<String> synonyms = new ArrayList<String>();
555 for (SynonymRelationship synRel :synRels ){
556 Synonym synonym = synRel.getSynonym();
557 SynonymRelationshipType type = synRel.getType();
558 if (type == null){ // should not happen
559 type = SynonymRelationshipType.SYNONYM_OF();
560 }
561 NonViralName<?> name = CdmBase.deproxy(synonym.getName(), NonViralName.class);
562 synonyms.add(name.getTitleCache());
563 }
564 record.setSynonyms(synonyms);
565 }
566
567 /**
568 *
569 * @param record
570 * @param taxon
571 */
572 private void handleDiscriptionData(CsvDemoRecord record, Taxon taxon) {
573
574 Set<TaxonDescription> descriptions = taxon.getDescriptions();
575 ArrayList<String> distributions = new ArrayList<String>();
576 for (TaxonDescription description : descriptions){
577 for (DescriptionElementBase el : description.getElements()){
578 if (el.isInstanceOf(Distribution.class) ){
579 Distribution distribution = CdmBase.deproxy(el, Distribution.class);
580 NamedArea area = distribution.getArea();
581 distributions.add(area.getTitleCache());
582 }
583
584 }
585 }
586 record.setCountryCode(distributions);
587 }
588 /**
589 *
590 * @param record
591 * @param taxon
592 * @param featureCells
593 * @param features
594 */
595 private void handleRedlistStatus(CsvDemoRecord record, Taxon taxon, List<List<String>> featureCells, List<Feature> features){
596 Set<TaxonDescription> descriptions = taxon.getDescriptions();
597
598 for (TaxonDescription description : descriptions){
599 for (DescriptionElementBase el : description.getElements()){
600 if(el.isInstanceOf(CategoricalData.class)){
601 CategoricalData categoricalData = CdmBase.deproxy(el, CategoricalData.class);
602 for(State state:categoricalData.getStatesOnly()){
603 Feature stateFeature = categoricalData.getFeature();
604 // find matching feature and put data into according cell
605 for(int i = 0; i < features.size(); i++) {
606 if(features.get(i).equals(stateFeature)){
607 List<String> cell = featureCells.get(i);
608 cell.add(state.toString());
609 }
610 }
611 }
612 }else if(el.isInstanceOf(TextData.class)){
613 TextData textData = CdmBase.deproxy(el, TextData.class);
614 Feature textFeature = textData.getFeature();
615 // find matching feature and put data into according cell
616 for(int i = 0; i < features.size(); i++) {
617 if(features.get(i).equals(textFeature)){
618 List<String> cell = featureCells.get(i);
619 String text = textData.getText(Language.GERMAN());
620 text = text.replaceAll(System.getProperty("line.separator"), "");
621 text = text.replaceAll(" ", " ");
622 cell.add(text);
623
624 }
625 }
626 }
627 }
628 }
629 record.setFeatures(featureCells);
630 }
631
632 /**
633 *
634 * @param record
635 * @param taxon
636 * @param relationFrom
637 * @param featureCells
638 * @param features
639 */
640 private void handleRelatedRedlistStatus(CsvDemoRecord record, Taxon taxon, boolean relationFrom, List<List<String>> featureCells, List<Feature> features) {
641
642 if (relationFrom) {
643 handleRedlistStatus(record, taxon, featureCells, features);
644 }
645
646
647 Set<TaxonRelationship> taxRels;
648 if(relationFrom){
649 taxRels = taxon.getRelationsFromThisTaxon();
650 }else{
651 taxRels = taxon.getRelationsToThisTaxon();
652 }
653 for (TaxonRelationship taxRel:taxRels){
654 if(taxRel.getType().equals(TaxonRelationshipType.CONGRUENT_TO())){
655 Taxon relatedTaxon;
656 if(relationFrom){
657 relatedTaxon = taxRel.getToTaxon();
658 }else{
659 relatedTaxon = taxRel.getFromTaxon();
660 }
661 handleRedlistStatus(record, relatedTaxon, featureCells, features);
662 }
663 }
664 }
665
666
667
668 /**
669 *
670 * @param taxonNodes
671 */
672 private void sortTaxonNodes(List<TaxonNode> taxonNodes) {
673 Collections.sort(taxonNodes, new Comparator<TaxonNode>() {
674
675 @Override
676 public int compare(TaxonNode tn1, TaxonNode tn2) {
677 Taxon taxon1 = tn1.getTaxon();
678 Taxon taxon2 = tn2.getTaxon();
679 if(taxon1 != null && taxon2 != null){
680 return taxon1.getTitleCache().compareTo(taxon2.getTitleCache());
681 }
682 else{
683 return 0;
684 }
685 }
686 });
687 }
688
689 @Override
690 protected boolean doCheck(CsvDemoExportState state) {
691 boolean result = true;
692 logger.warn("No check implemented for " + this.ioName);
693 return result;
694 }
695
696 @Override
697 protected boolean isIgnore(CsvDemoExportState state) {
698 return ! state.getConfig().isDoTaxa();
699 }
700
701 }