001 /** 002 * planningtool - A Planning Tool with Critiquing Support. 003 * 004 * Copyright (C) 2006 olale 005 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU General Public License 008 * as published by the Free Software Foundation; either version 2 009 * of the License, or (at your option) any later version. 010 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 016 * You should have received a copy of the GNU General Public License 017 * along with this program; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 019 020 * Contact information: 021 * E-mail: olale@ida.liu.se 022 * olale@lysator.liu.se 023 */ 024 package se.liu.ida.critiquer.activities.parameters; 025 026 import java.io.Serializable; 027 import java.util.concurrent.Semaphore; 028 029 import se.liu.ida.critiquer.activities.Activity; 030 031 /** 032 * This class describes the parameters that describe an activity 033 * 034 * When creating a plan, we start by choosing the type of activity 035 * which in turn gives us a template hierarchy of activities that 036 * we can start to manipulate 037 * 038 * This structure contains texttual information on missions and possibly 039 * time dependencies 040 * 041 * Next, resources are assigned to missions in the resource view by dragging 042 * resources to missions 043 * 044 * When this is done, time intervals for each mission can be calculated in 045 * the time view, according to one of several preconfigured settings (launch 046 * missions immediately after one another, set certain time slacks) 047 * 048 * Therefore, an activity parameter has a view associated with it where one 049 * can configure the parameter 050 * 051 * */ 052 public abstract class ActivityParameter<T> implements Parameter<T>, Serializable { 053 054 protected T value = null; 055 protected T oldValue = null; 056 /** 057 * If the user has ever set the value of this parameter, this will be true, otherwise false. 058 */ 059 protected boolean hasBeenSet = false; 060 061 private Activity activity; 062 private Semaphore valueUpdate = new Semaphore(1,true); 063 protected String name; 064 065 /** 066 * @param activity 067 */ 068 public ActivityParameter(String name, Activity activity) { 069 this.activity = activity; 070 this.name = name; 071 } 072 073 public abstract String toString(); 074 075 /** 076 * @return Returns the value. 077 */ 078 public T getValue() { 079 return value; 080 } 081 082 public boolean hasValue() { 083 return value!=null && hasBeenSet; 084 } 085 086 /** 087 * This method can be used directly by subclasses if the parameter value 088 * reference remaing the same but there has been changes to the value so 089 * listeners should be notified 090 * 091 * Also, we create a new thread to do the updating here since this may be 092 * called during the process of updating a parameter. 093 * 094 * 095 */ 096 097 protected void valueChanged() { 098 new Thread("\""+activity+"\":\""+name+"\" update thread") { 099 100 @Override 101 public void run() { 102 activity.signalParamChanged(ActivityParameter.this); 103 valueUpdate.release(); 104 } 105 106 }.start(); 107 108 } 109 110 /** 111 * 112 * Update the value of this parameter iff the value is consistent for this parameter 113 * The updating is performed with a binary semaphore set so that there can be no more than one thread updating and signalling activities of a value update 114 * 115 * @param value 116 * The value to set. Sets a value and notifies all listeners 117 * @return true if the change was consistent, false otherwise. 118 */ 119 public synchronized boolean setValue(T value) { 120 boolean consistent = false; 121 try { 122 valueUpdate.acquire(); 123 consistent = Activity.isConsistent(getActivity(), this, value); 124 if (consistent) { 125 oldValue = this.value; 126 this.value = value; 127 hasBeenSet=true; 128 valueChanged(); 129 } 130 131 } catch (InterruptedException e) { 132 System.err.println(name+".setValue interrupted"); 133 valueUpdate.release(); 134 } 135 return consistent; 136 } 137 138 /** 139 * @return Returns the name. 140 */ 141 public String getName() { 142 return name; 143 } 144 145 /** 146 * @param name 147 * The name to set. 148 */ 149 void setName(String name) { 150 this.name = name; 151 } 152 153 /** 154 * @return Returns the activity. 155 */ 156 public Activity getActivity() { 157 return activity; 158 } 159 160 /** 161 * @return Returns the oldValue. 162 */ 163 public T getOldValue() { 164 return oldValue; 165 } 166 167 }