View Javadoc
1   package fr.ifremer.tutti.ui.swing.content.operation.catches.species.edit;
2   
3   /*
4    * #%L
5    * Tutti :: UI
6    * %%
7    * Copyright (C) 2012 - 2014 Ifremer
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as
11   * published by the Free Software Foundation, either version 3 of the 
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Public 
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/gpl-3.0.html>.
22   * #L%
23   */
24  
25  import com.google.common.base.Preconditions;
26  import com.google.common.collect.Lists;
27  import fr.ifremer.adagio.core.dao.referential.ObjectTypeCode;
28  import fr.ifremer.tutti.persistence.entities.data.Attachment;
29  import fr.ifremer.tutti.persistence.entities.data.FishingOperation;
30  import fr.ifremer.tutti.persistence.entities.data.IndividualObservationBatch;
31  import fr.ifremer.tutti.persistence.entities.data.SampleCategory;
32  import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModel;
33  import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModelEntry;
34  import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch;
35  import fr.ifremer.tutti.persistence.entities.data.SpeciesBatchFrequency;
36  import fr.ifremer.tutti.persistence.entities.data.SpeciesBatchs;
37  import fr.ifremer.tutti.persistence.entities.referential.Caracteristic;
38  import fr.ifremer.tutti.persistence.entities.referential.Species;
39  import fr.ifremer.tutti.type.WeightUnit;
40  import fr.ifremer.tutti.ui.swing.content.operation.catches.species.frequency.IndividualObservationBatchRowModel;
41  import fr.ifremer.tutti.ui.swing.content.operation.catches.species.frequency.SpeciesFrequencyRowModel;
42  import fr.ifremer.tutti.ui.swing.util.AbstractTuttiBeanUIModel;
43  import fr.ifremer.tutti.ui.swing.util.attachment.AttachmentModelAware;
44  import fr.ifremer.tutti.ui.swing.util.computable.ComputableData;
45  import org.apache.commons.collections4.CollectionUtils;
46  import org.nuiton.jaxx.application.bean.JavaBeanObjectUtil;
47  import org.nuiton.util.beans.Binder;
48  import org.nuiton.util.beans.BinderFactory;
49  
50  import java.io.Serializable;
51  import java.util.Arrays;
52  import java.util.Collection;
53  import java.util.Collections;
54  import java.util.Iterator;
55  import java.util.List;
56  import java.util.Objects;
57  import java.util.Set;
58  
59  /**
60   * Represents a species batch (i.e a row in the batch table).
61   *
62   * @author Tony Chemit - chemit@codelutin.com
63   * @since 0.2
64   */
65  public class SpeciesBatchRowModel extends AbstractTuttiBeanUIModel<SpeciesBatch, SpeciesBatchRowModel> implements SpeciesBatch, AttachmentModelAware, SampleCategoryAble<SpeciesBatchRowModel> {
66  
67      private static final long serialVersionUID = 1L;
68  
69      public static final String PROPERTY_SPECIES_ROW = "speciesRow";
70  
71      public static final String PROPERTY_SAMPLE_CATEGORY = "sampleCategory";
72  
73      public static final String PROPERTY_SAMPLE_CATEGORY_VALUE = "sampleCategoryValue";
74  
75      public static final String PROPERTY_SAMPLE_CATEGORY_WEIGHT = "sampleCategoryWeight";
76  
77      public static final String PROPERTY_SAMPLE_CATEGORY_COMPUTED_WEIGHT = "sampleCategoryComputedWeight";
78  
79      public static final String PROPERTY_FREQUENCY = "frequency";
80  
81      public static final String PROPERTY_INDIVIDUAL_OBSERVATION = "individualObservation";
82  
83      public static final String PROPERTY_COMPUTED_NUMBER = "computedOrNotNumber";
84  
85      public static final String PROPERTY_COMPUTED_WEIGHT = "computedOrNotWeight";
86  
87      public static final String PROPERTY_CHILD_BATCH = "childBatch";
88  
89      public static final String PROPERTY_BATCH_LEAF = "batchLeaf";
90  
91      public static final String PROPERTY_BATCH_ROOT = "batchRoot";
92  
93      /**
94       * Delegate edit object.
95       *
96       * @since 1.3
97       */
98      protected final SpeciesBatch editObject = SpeciesBatchs.newSpeciesBatch();
99  
100     /**
101      * All categories(can not be null).
102      *
103      * @since 2.4
104      */
105     protected final SampleCategory<?>[] categories;
106 
107     /**
108      * Observed weight.
109      *
110      * @since 0.2
111      */
112     protected ComputableData<Float> computedOrNotWeight =
113             new ComputableData<>();
114 
115     /**
116      * Total computed number (from frequencies).
117      *
118      * @since 0.2
119      */
120     protected ComputableData<Integer> computedOrNotNumber =
121             new ComputableData<>();
122 
123     /**
124      * Attachments (should never be null).
125      *
126      * @since 0.2
127      */
128     protected final List<Attachment> attachment = Lists.newArrayList();
129 
130     /**
131      * List of frequencies observed for this batch.
132      *
133      * @since 0.2
134      */
135     protected List<SpeciesFrequencyRowModel> frequency = Lists.newArrayList();
136 
137     /**
138      * List of individual observations observed for this batch.
139      *
140      * @since 4.5
141      */
142     protected List<IndividualObservationBatchRowModel> individualObservation = Lists.newArrayList();
143 
144     /**
145      * List of child batches (can be null or empty if batch is a leaf).
146      *
147      * @see #isBatchLeaf()
148      * @since 0.3
149      */
150     protected List<SpeciesBatchRowModel> childBatch;
151 
152     /**
153      * Sample categories model.
154      *
155      * @since 2.4
156      */
157     protected final SampleCategoryModel sampleCategoryModel;
158 
159     /**
160      * Weight unit.
161      *
162      * @since 2.5
163      */
164     protected final WeightUnit weightUnit;
165 
166     protected static final Binder<SpeciesBatch, SpeciesBatchRowModel> fromBeanBinder =
167             BinderFactory.newBinder(SpeciesBatch.class,
168                                     SpeciesBatchRowModel.class);
169 
170     protected static final Binder<SpeciesBatchRowModel, SpeciesBatch> toBeanBinder =
171             BinderFactory.newBinder(SpeciesBatchRowModel.class,
172                                     SpeciesBatch.class);
173 
174     public SpeciesBatchRowModel(WeightUnit weightUnit,
175                                 SampleCategoryModel sampleCategoryModel) {
176         super(fromBeanBinder, toBeanBinder);
177         this.weightUnit = weightUnit;
178         this.sampleCategoryModel = sampleCategoryModel;
179         categories = new SampleCategory[sampleCategoryModel.getNbSampling()];
180 
181         for (int i = 0; i < categories.length; i++) {
182             SampleCategoryModelEntry entry = sampleCategoryModel.getCategoryByIndex(i);
183             SampleCategory<?> category = SampleCategory.newSample(entry);
184             categories[i] = category;
185         }
186 
187         computedOrNotWeight.addPropagateListener(PROPERTY_WEIGHT, this);
188         computedOrNotWeight.addPropagateListener(PROPERTY_COMPUTED_WEIGHT, this);
189         computedOrNotNumber.addPropagateListener(PROPERTY_NUMBER, this);
190         computedOrNotNumber.addPropagateListener(PROPERTY_COMPUTED_NUMBER, this);
191     }
192 
193     public SpeciesBatchRowModel getSpeciesRow() {
194         return this;
195     }
196 
197     public SpeciesBatchRowModel(WeightUnit weightUnit,
198                                 WeightUnit observationWeightUnit,
199                                 SampleCategoryModel sampleCategoryModel,
200                                 SpeciesBatch aBatch,
201                                 List<SpeciesBatchFrequency> frequencies,
202                                 List<IndividualObservationBatch> individualObservations,
203                                 List<Caracteristic> defautObservationCaracteristic) {
204         this(weightUnit, sampleCategoryModel);
205 
206         fromEntity(aBatch);
207 
208         loadFrequencies(frequencies);
209 
210         loadIndividualObservations(observationWeightUnit, defautObservationCaracteristic, individualObservations);
211 
212     }
213 
214     public void loadFrequencies(List<SpeciesBatchFrequency> frequencies) {
215 
216         List<SpeciesFrequencyRowModel> frequencyRows = SpeciesFrequencyRowModel.fromEntity(weightUnit, frequencies);
217         frequency.clear();
218         frequency.addAll(frequencyRows);
219         Collections.sort(frequency);
220 
221     }
222 
223     public void loadIndividualObservations(WeightUnit observationWeightUnit,
224                                            List<Caracteristic> defautObservationCaracteristic,
225                                            List<IndividualObservationBatch> individualObservations) {
226 
227         List<IndividualObservationBatchRowModel> obsRows =
228                 IndividualObservationBatchRowModel.fromEntity(observationWeightUnit, defautObservationCaracteristic, individualObservations);
229         individualObservation.clear();
230         individualObservation.addAll(obsRows);
231 
232     }
233 
234     //------------------------------------------------------------------------//
235     //-- AbstractTuttiBeanUIModel                                           --//
236     //------------------------------------------------------------------------//
237 
238     @Override
239     protected SpeciesBatch newEntity() {
240         return SpeciesBatchs.newSpeciesBatch();
241     }
242 
243     @Override
244     public void fromEntity(SpeciesBatch entity) {
245         super.fromEntity(entity);
246 
247         // convert weight
248         setWeight(weightUnit.fromEntity(getWeight()));
249         setComputedWeight(weightUnit.fromEntity(getComputedWeight()));
250     }
251 
252     @Override
253     public SpeciesBatch toEntity() {
254         SpeciesBatch result = super.toEntity();
255 
256         // convert weight
257         result.setWeight(weightUnit.toEntity(getWeight()));
258 
259         SampleCategory<?> sampleCategory = getFinestCategory();
260         Preconditions.checkNotNull(sampleCategory);
261         Preconditions.checkNotNull(sampleCategory.getCategoryId());
262         Preconditions.checkNotNull(sampleCategory.getCategoryValue());
263 
264         // apply sample category
265         result.setSampleCategoryId(sampleCategory.getCategoryId());
266         result.setSampleCategoryValue(sampleCategory.getCategoryValue());
267 
268         // convert sample category weight
269         Float categoryWeight = sampleCategory.getCategoryWeight();
270         result.setSampleCategoryWeight(weightUnit.toEntity(categoryWeight));
271 
272         return result;
273     }
274 
275     //------------------------------------------------------------------------//
276     //-- SpeciesBatch                                                       --//
277     //------------------------------------------------------------------------//
278 
279     @Override
280     public Species getSpecies() {
281         return editObject.getSpecies();
282     }
283 
284     @Override
285     public void setSpecies(Species species) {
286         Object oldCategory = getSpecies();
287         editObject.setSpecies(species);
288         firePropertyChange(PROPERTY_SPECIES, oldCategory, species);
289     }
290 
291     @Override
292     public String getComment() {
293         return editObject.getComment();
294     }
295 
296     @Override
297     public void setComment(String comment) {
298         Object oldValue = getComment();
299         editObject.setComment(comment);
300         firePropertyChange(PROPERTY_COMMENT, oldValue, comment);
301     }
302 
303     @Override
304     public boolean isSpeciesToConfirm() {
305         return editObject.isSpeciesToConfirm();
306     }
307 
308     @Override
309     public void setSpeciesToConfirm(boolean speciesToConfirm) {
310         boolean oldValue = isSpeciesToConfirm();
311         editObject.setSpeciesToConfirm(speciesToConfirm);
312         firePropertyChange(PROPERTY_SPECIES_TO_CONFIRM, oldValue, speciesToConfirm);
313     }
314 
315     @Override
316     public Integer getComputedNumber() {
317         return computedOrNotNumber.getComputedData();
318     }
319 
320     @Override
321     public void setComputedNumber(Integer computedNumber) {
322         computedOrNotNumber.setComputedData(computedNumber);
323     }
324 
325     @Override
326     public Float getComputedWeight() {
327         return computedOrNotWeight.getComputedData();
328     }
329 
330     @Override
331     public void setComputedWeight(Float computedWeight) {
332         computedOrNotWeight.setComputedData(computedWeight);
333     }
334 
335     @Override
336     public FishingOperation getFishingOperation() {
337         return editObject.getFishingOperation();
338     }
339 
340     @Override
341     public void setFishingOperation(FishingOperation fishingOperation) {
342         editObject.setFishingOperation(fishingOperation);
343     }
344 
345     @Override
346     public SpeciesBatchRowModel getParentBatch() {
347         return (SpeciesBatchRowModel) editObject.getParentBatch();
348     }
349 
350     @Override
351     public void setParentBatch(SpeciesBatch parentBatch) {
352         Object oldValue = getParentBatch();
353         editObject.setParentBatch(parentBatch);
354         firePropertyChange(PROPERTY_PARENT_BATCH, oldValue, parentBatch);
355         firePropertyChange(PROPERTY_BATCH_ROOT, null, isBatchRoot());
356     }
357 
358     @Override
359     public Float getWeight() {
360         return computedOrNotWeight.getData();
361     }
362 
363     @Override
364     public void setWeight(Float weight) {
365         this.computedOrNotWeight.setData(weight);
366     }
367 
368     @Override
369     public Integer getSampleCategoryId() {
370         return null;
371     }
372 
373     @Override
374     public void setSampleCategoryId(Integer sampleCategoryId) {
375     }
376 
377     @Override
378     public Serializable getSampleCategoryValue() {
379         return null;
380     }
381 
382     @Override
383     public void setSampleCategoryValue(Serializable sampleCategoryValue) {
384     }
385 
386     @Override
387     public Float getSampleCategoryWeight() {
388         return null;
389     }
390 
391     @Override
392     public void setSampleCategoryWeight(Float sampleCategoryWeight) {
393     }
394 
395     @Override
396     public Integer getNumber() {
397         return computedOrNotNumber.getData();
398     }
399 
400     @Override
401     public void setNumber(Integer number) {
402         computedOrNotNumber.setData(number);
403     }
404 
405     @Override
406     public Float getSampleCategoryComputedWeight() {
407         return null;
408     }
409 
410     @Override
411     public void setSampleCategoryComputedWeight(Float sampleCategoryComputedWeight) {
412     }
413 
414     @Override
415     public SpeciesBatch getChildBatchs(int index) {
416         return childBatch.get(index);
417     }
418 
419     @Override
420     public boolean isChildBatchsEmpty() {
421         return childBatch == null || childBatch.isEmpty();
422     }
423 
424     @Override
425     public int sizeChildBatchs() {
426         return childBatch == null ? 0 : childBatch.size();
427     }
428 
429     @Override
430     public void addChildBatchs(SpeciesBatch childBatchs) {
431     }
432 
433     @Override
434     public void addAllChildBatchs(Collection<SpeciesBatch> childBatchs) {
435     }
436 
437     @Override
438     public boolean removeChildBatchs(SpeciesBatch childBatchs) {
439         return false;
440     }
441 
442     @Override
443     public boolean removeAllChildBatchs(Collection<SpeciesBatch> childBatchs) {
444         return false;
445     }
446 
447     @Override
448     public boolean containsChildBatchs(SpeciesBatch childBatchs) {
449         return false;
450     }
451 
452     @Override
453     public boolean containsAllChildBatchs(Collection<SpeciesBatch> childBatchs) {
454         return false;
455     }
456 
457     @Override
458     public List<SpeciesBatch> getChildBatchs() {
459         return null;
460     }
461 
462     @Override
463     public void setChildBatchs(List childBatchs) {
464     }
465 
466     @Override
467     public Integer getRankOrder() {
468         return editObject.getRankOrder();
469     }
470 
471     @Override
472     public void setRankOrder(Integer rankOrder) {
473         editObject.setRankOrder(rankOrder);
474     }
475 
476     @Override
477     public boolean isBenthosBatch() {
478         return editObject.isBenthosBatch();
479     }
480 
481     @Override
482     public void setBenthosBatch(boolean benthosBatch) {
483         //NEVER!
484     }
485 
486     //------------------------------------------------------------------------//
487     //-- SampleCategoryAble                                                 --//
488     //------------------------------------------------------------------------//
489 
490     @Override
491     public Integer getCategoryIndex(Integer id) {
492         int result = 0;
493         for (SampleCategory<?> category : categories) {
494             if (category != null && id.equals(category.getCategoryId())) {
495                 break;
496             } else {
497                 result++;
498             }
499         }
500         return result;
501     }
502 
503     @Override
504     public void setSampleCategory(SampleCategory sampleCategory) {
505         int index = getCategoryIndex(sampleCategory.getCategoryId());
506         SampleCategory<?> oldCategory = categories[index];
507         Object oldValue = oldCategory.getCategoryValue();
508         Object oldWeight = oldCategory.getCategoryWeight();
509         Object oldComputedWeight = oldCategory.getComputedWeight();
510         categories[index] = sampleCategory;
511 
512         //FIXME (indexed)
513         fireIndexedPropertyChange(PROPERTY_SAMPLE_CATEGORY, index, oldCategory, sampleCategory);
514         fireIndexedPropertyChange(PROPERTY_SAMPLE_CATEGORY_VALUE, index, oldValue, sampleCategory.getCategoryValue());
515         fireIndexedPropertyChange(PROPERTY_SAMPLE_CATEGORY_WEIGHT, index, oldWeight, sampleCategory.getCategoryWeight());
516         fireIndexedPropertyChange(PROPERTY_SAMPLE_CATEGORY_COMPUTED_WEIGHT, index, oldComputedWeight, sampleCategory.getComputedWeight());
517     }
518 
519     @Override
520     public SampleCategory<?> getSampleCategoryById(Integer sampleCategoryId) {
521         Integer index = getCategoryIndex(sampleCategoryId);
522         return index == null ? null : categories[index];
523     }
524 
525     @Override
526     public SampleCategory<?> getSampleCategoryByIndex(int sampleCategoryIndex) {
527         return categories[sampleCategoryIndex];
528     }
529 
530     @Override
531     public Serializable getSampleCategoryValue(Integer sampleCategoryId) {
532         SampleCategory<?> sampleCategory = getSampleCategoryById(sampleCategoryId);
533         return (Serializable) JavaBeanObjectUtil.getProperty(sampleCategory, SampleCategory.PROPERTY_CATEGORY_VALUE);
534     }
535 
536     @Override
537     public void setSampleCategoryValue(Integer sampleCategoryId, Serializable value) {
538         SampleCategory<?> sampleCategory =
539                 getSampleCategoryById(sampleCategoryId);
540         JavaBeanObjectUtil.setProperty(sampleCategory,
541                                        SampleCategory.PROPERTY_CATEGORY_VALUE, value);
542         firePropertyChange(PROPERTY_SAMPLE_CATEGORY_VALUE, null, sampleCategory);
543     }
544 
545     @Override
546     public void setSampleCategoryWeight(Integer sampleCategoryId, Object value) {
547         SampleCategory<?> sampleCategory =
548                 getSampleCategoryById(sampleCategoryId);
549         JavaBeanObjectUtil.setProperty(sampleCategory,
550                                        SampleCategory.PROPERTY_CATEGORY_WEIGHT, value);
551         firePropertyChange(PROPERTY_SAMPLE_CATEGORY_WEIGHT, null, sampleCategory);
552     }
553 
554     @Override
555     public SampleCategory getFinestCategory() {
556         SampleCategory result = null;
557         for (int i = categories.length - 1; i > -1; i--) {
558             SampleCategory<?> category = categories[i];
559             if (category != null && category.isValid()) {
560                 result = category;
561                 break;
562             }
563         }
564         return result;
565     }
566 
567     @Override
568     public SampleCategory<?> getFirstSampleCategory() {
569         return categories[0];
570     }
571 
572     @Override
573     public SpeciesBatchRowModel getFirstAncestor(SampleCategory<?> entrySampleCategory) {
574         SpeciesBatchRowModel result = this;
575         if (getParentBatch() != null) {
576             SpeciesBatchRowModel parentBatch = getParentBatch();
577             SampleCategory<?> parentSampleCategory = parentBatch.getSampleCategoryById(entrySampleCategory.getCategoryId());
578             if (Objects.equals(entrySampleCategory, parentSampleCategory)) {
579 
580                 result = parentBatch.getFirstAncestor(entrySampleCategory);
581             }
582         }
583         return result;
584     }
585 
586     @Override
587     public Iterator<SampleCategory<?>> iterator() {
588         return Arrays.asList(categories).iterator();
589     }
590 
591     //------------------------------------------------------------------------//
592     //-- AttachmentModelAware                                               --//
593     //------------------------------------------------------------------------//
594 
595     @Override
596     public ObjectTypeCode getObjectType() {
597         return ObjectTypeCode.BATCH;
598     }
599 
600     @Override
601     public Integer getObjectId() {
602         return getIdAsInt();
603     }
604 
605     @Override
606     public List<Attachment> getAttachment() {
607         return attachment;
608     }
609 
610     @Override
611     public void addAllAttachment(Collection<Attachment> attachments) {
612         this.attachment.addAll(attachments);
613         firePropertyChange(PROPERTY_ATTACHMENT, null, getAttachment());
614     }
615 
616     @Override
617     public void addAttachment(Attachment attachment) {
618         this.attachment.add(attachment);
619         firePropertyChange(PROPERTY_ATTACHMENT, null, getAttachment());
620     }
621 
622     @Override
623     public void removeAllAttachment(Collection<Attachment> attachments) {
624         this.attachment.removeAll(attachments);
625         firePropertyChange(PROPERTY_ATTACHMENT, null, getAttachment());
626     }
627 
628     @Override
629     public void removeAttachment(Attachment attachment) {
630         this.attachment.remove(attachment);
631         firePropertyChange(PROPERTY_ATTACHMENT, null, getAttachment());
632     }
633 
634     //------------------------------------------------------------------------//
635     //-- Other properties                                                   --//
636     //------------------------------------------------------------------------//
637 
638     public SpeciesBatchRowModel getFirstAncestor(Integer sampleCategoryId) {
639         SampleCategory<?> sampleCategory = getSampleCategoryById(sampleCategoryId);
640         return getFirstAncestor(sampleCategory);
641     }
642 
643     public List<SpeciesBatchRowModel> getChildBatch() {
644         return childBatch;
645     }
646 
647     public void setChildBatch(List<SpeciesBatchRowModel> childBatch) {
648         this.childBatch = childBatch;
649         // force to propagate child changes
650         firePropertyChange(PROPERTY_CHILD_BATCH, null, childBatch);
651         firePropertyChange(PROPERTY_BATCH_LEAF, null, isBatchLeaf());
652     }
653 
654     public boolean isBatchLeaf() {
655         return CollectionUtils.isEmpty(childBatch);
656     }
657 
658     public boolean isBatchRoot() {
659         return getParentBatch() == null;
660     }
661 
662     public List<SpeciesFrequencyRowModel> getFrequency() {
663         return frequency;
664     }
665 
666     public void setFrequency(List<SpeciesFrequencyRowModel> frequency) {
667         this.frequency = frequency;
668         // force to propagate frequencies changes
669         firePropertyChange(PROPERTY_FREQUENCY, null, frequency);
670     }
671 
672     public List<IndividualObservationBatchRowModel> getIndividualObservation() {
673         return individualObservation;
674     }
675 
676     public void setIndividualObservation(List<IndividualObservationBatchRowModel> individualObservation) {
677         this.individualObservation = individualObservation;
678         // force to propagate observation changes
679         firePropertyChange(PROPERTY_INDIVIDUAL_OBSERVATION, null, individualObservation);
680     }
681 
682     public ComputableData<Integer> getComputedOrNotNumber() {
683         return computedOrNotNumber;
684     }
685 
686     public void setComputedOrNotNumber(ComputableData<Integer> computedOrNotNumber) {
687         this.computedOrNotNumber = computedOrNotNumber;
688     }
689 
690     public ComputableData<Float> getComputedOrNotWeight() {
691         return computedOrNotWeight;
692     }
693 
694     public void setComputedOrNotWeight(ComputableData<Float> computedOrNotWeight) {
695         this.computedOrNotWeight = computedOrNotWeight;
696     }
697 
698     public void collectShell(Set<SpeciesBatchRowModel> collectedRows) {
699 
700         collectedRows.add(this);
701 
702         if (!isBatchLeaf()) {
703 
704             for (SpeciesBatchRowModel batchChild : getChildBatch()) {
705                 collectedRows.add(batchChild);
706                 batchChild.collectShell(collectedRows);
707             }
708         }
709     }
710 
711     public boolean containsIndividualObservations(boolean withSampleCode) {
712 
713         boolean result;
714         if (withSampleCode) {
715             result = false;
716             for (IndividualObservationBatchRowModel obs : getIndividualObservation()) {
717                 result = obs.getSamplingCode() != null;
718                 if (result) {
719                     break;
720                 }
721             }
722         } else {
723             result = CollectionUtils.isNotEmpty(getIndividualObservation());
724         }
725 
726         if (!result && !isChildBatchsEmpty()) {
727 
728             for (SpeciesBatchRowModel childRow : childBatch) {
729                 result = childRow.containsIndividualObservations(withSampleCode);
730                 if (result) {
731                     break;
732                 }
733             }
734         }
735 
736         return result;
737     }
738 
739 }