source: src/main/java/geniusweb/partiesserver/repository/RunningParty.java@ 40

Last change on this file since 40 was 40, checked in by bart, 3 years ago

Added python SimpleRunner GUI

File size: 8.3 KB
Line 
1package geniusweb.partiesserver.repository;
2
3import java.net.InetAddress;
4import java.net.UnknownHostException;
5import java.util.Date;
6import java.util.UUID;
7
8import com.fasterxml.jackson.annotation.JsonAutoDetect;
9import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
10
11import geniusweb.actions.PartyId;
12import geniusweb.inform.Inform;
13import geniusweb.partiesserver.RunningPartiesUpdater;
14import geniusweb.partiesserver.websocket.PartySocket;
15import geniusweb.party.Party;
16import tudelft.utilities.repository.RepoElement;
17
18/**
19 * Contains a running party and additional info about it like time constraints
20 * and connections. Adds a start/end times and generates party ID. Also stores
21 * original filename of the party.
22 *
23 * This object can not be deserialized here because running parties have to be
24 * created.
25 */
26@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
27public class RunningParty implements RepoElement<PartyId> {
28 private static int nr = 1; // counter for generating unique new parties.
29 private static String uniqueid = getUniqueMachineID(); // world-wide unique
30 // ID for this
31 // number. For ID
32 // generation.
33
34 private final PartyId id;
35 private final Date startDate;
36 private final Date endDate; // agent will be declared dead and removed after
37 // this
38 private final String name;
39 /*
40 * set when someone contacts our socket. null if not set.
41 */
42 private final transient PartySocket connection;
43
44 /**
45 * The actually running party
46 */
47 private transient final Party party;
48
49 /**
50 * Only available for testing.
51 *
52 * @param party the new party
53 * @param id the new id for the party.
54 * @param name the name, this should match the filename
55 * @param start the start date for this party. Usually set to current time.
56 * @param end the end date for this party
57 * @param conn the connection to use, or null if no connection is available
58 * yet.
59 */
60 protected RunningParty(Party party, PartyId id, String name, Date start,
61 Date end, PartySocket conn) {
62 if (party == null || id == null || name == null || start == null
63 || end == null) {
64 throw new NullPointerException("arguments must not be null");
65 }
66 this.party = party;
67 this.id = id;
68 this.name = name;
69 this.startDate = start;
70 this.endDate = end;
71 this.connection = conn;
72 }
73
74 /**
75 * @param availableparty the {@link AvailableParty}
76 * @param maxlifetimems the maximum life time for this party (ms). The
77 * party will be killed and removed after this point.
78 * This value should be set to the maximum negotiation
79 * time plus the worst time to actual start up of the
80 * negotiation
81 * @return a new RunningParty being an instance of availableparty
82 * @throws InstantiationFailedException if class can not be instantiated
83 *
84 */
85 public static RunningParty create(AvailableParty availableparty,
86 long maxlifetimems) throws InstantiationFailedException {
87 if (availableparty == null) {
88 throw new IllegalArgumentException(
89 "availableparty must not be null");
90 }
91 return create(availableparty.getInstance(), availableparty.getName(),
92 maxlifetimems);
93 }
94
95 /**
96 * Create a running party.
97 *
98 * @param party the {@link Party} that is loaded and ready to run.
99 * @param name The name, this should match the filename in the repo
100 * (without the .jar).
101 * @param maxRunTimeMS the maximum runtime for this party (ms). The
102 * {@link RunningPartiesUpdater} will keep an eye on the
103 * time and handle removal after time is up.
104 * @return new RunningParty created from the Party instance.
105 *
106 */
107 private static RunningParty create(Party party, String name,
108 long maxRunTimeMS) {
109 if (maxRunTimeMS <= 0) {
110 throw new IllegalArgumentException("runtime must be >0");
111 }
112 Date now = new Date();
113 return new RunningParty(party,
114 new PartyId(squash1(name) + "_" + uniqueid + "_" + (nr++)),
115 name, now, new Date(now.getTime() + maxRunTimeMS), null);
116 }
117
118 /**
119 * @return unique ID for this running party
120 */
121 @Override
122 public PartyId getID() {
123 return id;
124 }
125
126 /**
127 * @return the implementation of this party
128 */
129 public Party getParty() {
130 return party;
131 }
132
133 /**
134 * @return The name, this should match the filename in the repo (without the
135 * .jar).
136 *
137 */
138 public String getName() {
139 return name;
140 }
141
142 /**
143 * @return the start {@link Date} of this runningparty.
144 */
145 public Date getStartDate() {
146 return startDate;
147 }
148
149 /**
150 *
151 * @return the end date/ deadline for this party
152 */
153 public Date getEndDate() {
154 return endDate;
155 }
156
157 @Override
158 public int hashCode() {
159 final int prime = 31;
160 int result = 1;
161 result = prime * result + ((id == null) ? 0 : id.hashCode());
162 result = prime * result + ((name == null) ? 0 : name.hashCode());
163 result = prime * result + ((party == null) ? 0 : party.hashCode());
164 result = prime * result
165 + ((startDate == null) ? 0 : startDate.hashCode());
166 return result;
167 }
168
169 @Override
170 public boolean equals(Object obj) {
171 if (this == obj)
172 return true;
173 if (obj == null)
174 return false;
175 if (getClass() != obj.getClass())
176 return false;
177 RunningParty other = (RunningParty) obj;
178 if (id == null) {
179 if (other.id != null)
180 return false;
181 } else if (!id.equals(other.id))
182 return false;
183 if (name == null) {
184 if (other.name != null)
185 return false;
186 } else if (!name.equals(other.name))
187 return false;
188 if (party == null) {
189 if (other.party != null)
190 return false;
191 } else if (!party.equals(other.party))
192 return false;
193 if (startDate == null) {
194 if (other.startDate != null)
195 return false;
196 } else if (!startDate.equals(other.startDate))
197 return false;
198 return true;
199 }
200
201 @Override
202 public String toString() {
203 return "RunningParty[" + id + "," + startDate + party.getClass() + ","
204 + name + "]";
205 }
206
207 /**
208 * Pass {@link Inform} into the running party. You must have called
209 * {@link #withConnection(PartySocket)} before calling this.
210 *
211 * @param info the {@link Inform} to be sent to the {@link #connection}
212 */
213 public void inform(Inform info) {
214 connection.notifyListeners(info);
215 }
216
217 /**
218 * Attach RunningParty to a connection. We allow at most 1 connection.
219 *
220 * @param newconn the new connection that has been made with this party.
221 * @return new RunningParty. This must be inserted into the
222 * {@link RunningPartiesRepo} by the caller.
223 * @throws IllegalStateException if the party is already connected.
224 */
225 public RunningParty withConnection(PartySocket newconn) {
226 if (newconn == null)
227 throw new NullPointerException("newconn must be not null");
228 if (this.connection != null) {
229 throw new IllegalStateException(
230 "RunningParty is already connected");
231 }
232 party.connect(newconn);
233 return new RunningParty(party, id, name, startDate, endDate, newconn);
234 }
235
236 /**
237 *
238 * @param terminationTime the new termination time
239 * @return new RunningParty with changed end time (all other things
240 * unchanged)
241 */
242 public RunningParty withEndTime(Date terminationTime) {
243 return new RunningParty(party, id, name, startDate, terminationTime,
244 connection);
245 }
246
247 /**
248 * Get a id that is world-wide unique. We use the IP number here instead of
249 * UUID because UUID usually is just a random number which is (1) long (22
250 * bytes) (2) not guaranteed unique.
251 */
252 private static String getUniqueMachineID() {
253 if (uniqueid == null) {
254 try {
255 uniqueid = InetAddress.getLocalHost().getHostAddress();
256 } catch (UnknownHostException e1) {
257 uniqueid = UUID.randomUUID().toString(); // fallback, should
258 // never be needed
259 }
260 uniqueid = squash(uniqueid);
261 }
262 return uniqueid;
263 }
264
265 /**
266 *
267 * @param string
268 * @return string with all non-word characters replaced with "_" so that the
269 * result is a "word" ( [a-zA-Z_0-9] ).
270 */
271 protected static String squash(String string) {
272 return string.replaceAll("\\W", "_");
273 }
274
275 /**
276 * @param string
277 * @return as squash, but additionally if the name does not start with a
278 * letter we prefix the string with 'p'
279 */
280 protected static String squash1(String string) {
281 String res = squash(string);
282 if (res.matches("[a-zA-Z]\\w*"))
283 return res;
284 return "p" + res;
285 }
286
287}
Note: See TracBrowser for help on using the repository browser.