All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nl.cloudfarming.client.farm.model.CropProductionUnit Maven / Gradle / Ivy

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