
nl.cloudfarming.client.farm.model.CropProductionUnit Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of farm-model Show documentation
Show all versions of farm-model Show documentation
AgroSense Farm model - contains model/domain classes for farm modules
The newest version!
/**
* Copyright (C) 2008-2012 AgroSense Foundation.
*
* AgroSense is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* There are special exceptions to the terms and conditions of the GPLv3 as it is applied to
* this software, see the FLOSS License Exception
* .
*
* AgroSense is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AgroSense. If not, see .
*/
package nl.cloudfarming.client.farm.model;
import java.awt.Color;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import nl.cloudfarming.client.crop.model.Classification;
import nl.cloudfarming.client.crop.model.Crop;
import nl.cloudfarming.client.crop.model.CropInstance;
import nl.cloudfarming.client.crop.model.Variety;
import nl.cloudfarming.client.field.model.Field;
import nl.cloudfarming.client.model.AbstractEntity;
import nl.cloudfarming.client.model.EnterpriseIdProvider;
import nl.cloudfarming.client.model.ItemIdType;
import nl.cloudfarming.client.model.Temporal;
/**
* Model class for production unit.
*
* A crop production unit is an administrative unit and collection of crop
* fields.
*
* @author Timon Veenstra
*/
public class CropProductionUnit extends AbstractEntity implements Serializable, PropertyChangeListener, Temporal {
public static final ItemIdType ITEM_ID_TYPE = ItemIdType.CPU;
public static final String MIME_TYPE = "application/x-agrosense-cropproductionunit";
public static final String EXT = ITEM_ID_TYPE.defaultExt();
public static final String PROP_CROPINSTANCE = "cropInstance";
public static final String PROP_PLANNED_AREA_IN_HECTARES = "plannedAreaInHectares";
public static final String PROP_ACTUAL_AREA_IN_HECTARES = "actualAreaInHectares";
public static final String PROP_DESCRIPTION = "description";
public static final String PROP_NAME = "name";
public static final String PROP_START_DATE = "startDate";
public static final String PROP_END_DATE = "endDate";
public static final String PROP_CROPFIELDS = "cropFields";
public static final String PROP_COLOR = "color";
private Double plannedAreaInHectares;
private double actualAreaInHectares;
private String name;
private String description;
private Date startDate;
private Date endDate;
private List cropFields = new ArrayList<>();
private CropInstance cropInstance;
private Color color;
public CropProductionUnit(EnterpriseIdProvider eip) {
super(eip, ITEM_ID_TYPE);
}
public CropProductionUnit(EnterpriseIdProvider eip, CropInstance instance) {
super(eip, ITEM_ID_TYPE);
setCropInstance(instance);
}
public final void setCropInstance(CropInstance cropInstance) {
CropInstance oldInstance = this.cropInstance;
this.cropInstance = cropInstance;
getPropertyChangeSupport().firePropertyChange(PROP_CROPINSTANCE, oldInstance, cropInstance);
initPropertyChangeListeners();
}
private void initPropertyChangeListeners() {
cropInstance.addPropertyChangeListener(new CropInstanceChangeListener());
for (CropField cropField : getCropFields()) {
initCropFieldPropertyChangeListener(cropField);
}
}
private void initCropFieldPropertyChangeListener(CropField cropField) {
cropField.addPropertyChangeListener(this);
}
/**
* Get the {@link CropInstance} of this CropProductionUnit
*
* @return
*/
public CropInstance getCropInstance() {
return cropInstance;
}
/**
* Get the {@link Crop} of this CropProductionUnit
*
* @return
*/
public Crop getCrop() {
return cropInstance.getCrop();
}
/**
* Get the {@link Variety} of this CropProductionUnit
*
* @return
*/
public Variety getVariety() {
return cropInstance.getVariety();
}
/**
* Get the {@link Classification} of this CropProductionUnit
*
* @return
*/
public Classification getClassification() {
return cropInstance.getClassification();
}
/**
* Get the {@link Color} of this CropProductionUnit
if the color
* of this CropProductionUnit is not set it will return the Color of it's {@link Crop}
s
*
* @return
*/
public Color getColor() {
if (color == null) {
return cropInstance.getColor();
} else {
return color;
}
}
public void setColor(Color color) {
Color oldColor = this.color;
this.color = color;
setCropFieldColor(oldColor, color);
getPropertyChangeSupport().firePropertyChange(PROP_COLOR, oldColor, color);
}
private void setCropFieldColor(Color oldColor, Color newColor){
for(CropField cropField : cropFields){
cropField.setColorChanged(oldColor, newColor);
}
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
String oldName = this.name;
this.name = name;
getPropertyChangeSupport().firePropertyChange(PROP_NAME, oldName, name);
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
String oldDescription = this.description;
this.description = description;
getPropertyChangeSupport().firePropertyChange(PROP_DESCRIPTION, oldDescription, description);
}
@Override
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
Date oldEndDate = this.endDate;
this.endDate = endDate;
getPropertyChangeSupport().firePropertyChange(PROP_END_DATE, oldEndDate, endDate);
}
@Override
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
Date oldStartDate = this.startDate;
this.startDate = startDate;
getPropertyChangeSupport().firePropertyChange(PROP_START_DATE, oldStartDate, startDate);
}
/**
* Get the planned area in HA of this production unit
*
* @return
*/
public Double getPlannedAreaInHectares() {
return plannedAreaInHectares;
}
/**
* Get the actual area in HA of this production unit
*/
public Double getActualAreaInHectares() {
return actualAreaInHectares;
}
/**
* Set the planned area of this production unit in HA
*
* @param plannedAreaInHectares
*/
public void setPlannedAreaInHectares(Double plannedAreaInHectares) {
Double oldPlannedAreaInHectares = this.plannedAreaInHectares;
this.plannedAreaInHectares = plannedAreaInHectares;
getPropertyChangeSupport().firePropertyChange(PROP_PLANNED_AREA_IN_HECTARES, oldPlannedAreaInHectares, plannedAreaInHectares);
}
/**
* Get the {@link CropField} this CropProductionUnit contains
*
* @return an unmodifiableList use {
* @see
* CropProductionUnit#addCropField(nl.cloudfarming.client.farm.model.CropField)}
* to add CropFields
*/
public List getCropFields() {
return Collections.unmodifiableList(cropFields);
}
/**
* Add a {@link CropField} to this CropProductionUnit If the production
* unit does not yet contain a crop field that stems from the same field as
* the {@link CropField} passed in the parameter.
Fires a
* {@link PropertyChangeEvent} with
* {@link PropertyChangeEvent#propertyName} {@link CropProductionUnit#PROP_CROPFIELDS}
*
* FIXME: disabled the stem part. There could be a number of crop fields in
* a production unit that stem from the same field. They just can't overlap
* with each other. See AGROSENSE-1108
*
* @param cropField The crop field that is to be added to the PU
*/
public void addCropField(CropField cropField) {
//if (!containsFieldById(cropField.getFieldId(), cropField.getFieldEnterpriseId())) {
doAddCropField(cropField);
//}
}
/**
* Create a crop field from a field and add the newly created crop field to
* the PU if this PU does not contain any crop fields that stem from the
* field passed as the parameter.
*
* @param field The field that should be used to create a crop field and
* added to the PU
*/
public void addCropFieldFromField(Field field) {
if (!containsField(field)) {
CropField cropField = createCropFieldFromField(field);
doAddCropField(cropField);
}
}
/**
* Method that actually adds the crop field to the list of crop fields of
* this PU.
*
* @param cropField The crop field that should be added to the PU
*/
protected void doAddCropField(CropField cropField) {
List oldCropFields = new ArrayList<>(getCropFields());
cropFields.add(cropField);
cropField.setParentURI(getURI());
initCropFieldPropertyChangeListener(cropField);
recalcCurrentArea();
getPropertyChangeSupport().firePropertyChange(PROP_CROPFIELDS, oldCropFields, getCropFields());
}
private void setActualAreaInHectares(Double area) {
double oldValue = this.actualAreaInHectares;
actualAreaInHectares = area;
getPropertyChangeSupport().firePropertyChange(PROP_ACTUAL_AREA_IN_HECTARES, oldValue, actualAreaInHectares);
}
/**
* Checks if the list of crop fields contains any crop fields that stem from
* a field with the same URI as the field passed as the parameter.
*
* @param field
* @return True if the list of crop fields contains a crop field that stems
* from a field with the same URI as the field passed as the parameter,
* false otherwise
*/
private boolean containsField(Field field) {
for (CropField cropField : getCropFields()) {
if (cropField.getFieldURI().equals(field.getURI())) {
return true;
}
}
return false;
}
/**
* Creates a new crop field from a field.
*
* @param field The field that should be used to create the crop field
* @return A new crop field with the properties of the field passed as the
* parameter.
*/
private CropField createCropFieldFromField(Field field) {
CropField cropField = new CropField(field);
cropField.setStartDate(new Date());
cropField.setEndDate(field.getEndDate()); // FIXME: Enddata cannot be > field enddate
// cropField.setAreaInHectares(field.getGeometry().getArea()); // FIXME: Convert to ha
cropField.setGeometry(field.getGeometry());
cropField.setName(field.getName());
return cropField;
}
/**
* Removes a {@link CropField} from this CropProductionUnit
Fires
* a {@link PropertyChangeEvent} with
* {@link PropertyChangeEvent#propertyName} {@link CropProductionUnit#PROP_CROPFIELDS}
*
* @param cropField
*/
public void removeCropField(CropField cropField) {
List oldCropFields = new ArrayList<>(getCropFields());
cropFields.remove(cropField);
cropField.removePropertyChangeListener(this);
cropField.setParentURI(null);
recalcCurrentArea();
getPropertyChangeSupport().firePropertyChange(PROP_CROPFIELDS, oldCropFields, getCropFields());
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
initPropertyChangeListeners();
// may have passed start or end date since the last time the object was read:
recalcCurrentArea();
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getSource() instanceof CropField) {
List props = Arrays.asList(CropField.PROP_AREA_IN_HECTARES, CropField.PROP_START_DATE, CropField.PROP_END_DATE);
if (props.contains(evt.getPropertyName())) {
recalcCurrentArea();
}
getPropertyChangeSupport().firePropertyChange(PROP_CROPFIELDS, null, evt.getSource());
}
}
private void recalcCurrentArea() {
Date today = new Date();
setActualAreaInHectares(getAreaInHectaresOn(today));
}
/**
* Calculate the actual area in hectares on a specific date.
* Cropfields whose validity period includes the date are included in the total.
*
* @param when
* @return
*/
public double getAreaInHectaresOn(Date when) {
double area = 0;
for (CropField cf : cropFields) {
// TODO: add DateRange utilities
if (cf.getStartDate().before(when) && (cf.getEndDate() == null || cf.getEndDate().after(when))) {
area += cf.getAreaInHectares();
}
}
return area;
}
private class CropInstanceChangeListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (CropInstance.PROP_COLOR.equals(evt.getPropertyName())) {
if (CropProductionUnit.this.color == null) {
setCropFieldColor((Color) evt.getOldValue(), (Color)evt.getNewValue());
getPropertyChangeSupport().firePropertyChange(CropProductionUnit.PROP_COLOR, evt.getOldValue(), evt.getNewValue());
}
}
}
}
@Override
public List getTemporalChildren() {
List children = new ArrayList<>();
children.addAll(getCropFields());
return children;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy