Commit | Line | Data |
---|---|---|
73005152 | 1 | /********************************************************************** |
ed902a2b | 2 | * Copyright (c) 2005, 2014 IBM Corporation, Ericsson |
73005152 BH |
3 | * All rights reserved. This program and the accompanying materials |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
013a5f1c AM |
7 | * |
8 | * Contributors: | |
c8422608 AM |
9 | * IBM - Initial API and implementation |
10 | * Bernd Hufmann - Updated for TMF | |
73005152 | 11 | **********************************************************************/ |
c8422608 | 12 | |
2bdf0193 | 13 | package org.eclipse.tracecompass.tmf.ui.views.uml2sd.core; |
73005152 BH |
14 | |
15 | import java.util.Comparator; | |
16 | ||
2bdf0193 AM |
17 | import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp; |
18 | import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp; | |
19 | import org.eclipse.tracecompass.tmf.ui.views.uml2sd.drawings.IGC; | |
20 | import org.eclipse.tracecompass.tmf.ui.views.uml2sd.preferences.ISDPreferences; | |
21 | import org.eclipse.tracecompass.tmf.ui.views.uml2sd.preferences.SDViewPref; | |
22 | import org.eclipse.tracecompass.tmf.ui.views.uml2sd.util.SortAsyncForBackward; | |
23 | import org.eclipse.tracecompass.tmf.ui.views.uml2sd.util.SortAsyncMessageComparator; | |
73005152 BH |
24 | |
25 | /** | |
26 | * A AsyncMessage is a asynchronous message which appear at two different event occurrences on each lifeline ends (sender | |
27 | * and receiver).<br> | |
28 | * <br> | |
29 | * <br> | |
30 | * Usage example: | |
013a5f1c | 31 | * |
73005152 BH |
32 | * <pre> |
33 | * Frame frame; | |
34 | * Lifeline lifeLine1; | |
35 | * Lifeline lifeLine2; | |
013a5f1c | 36 | * |
73005152 BH |
37 | * AsyncMessage message = new AsyncMessage(); |
38 | * // Create a new event occurrence on each lifeline | |
39 | * lifeline1.getNewOccurrenceIndex(); | |
40 | * lifeline2.getNewOccurrenceIndex(); | |
41 | * // Set the message sender and receiver | |
42 | * message.setStartLifeline(lifeLine1); | |
43 | * message.setEndLifline(lifeline2); | |
44 | * message.setName("Message label"); | |
45 | * // add the message to the frame | |
46 | * frame.addMessage(message); | |
47 | * </pre> | |
013a5f1c | 48 | * |
73005152 | 49 | * @see Lifeline Lifeline for more event occurence details |
013a5f1c | 50 | * @version 1.0 |
73005152 | 51 | * @author sveyrier |
73005152 BH |
52 | */ |
53 | public class AsyncMessage extends BaseMessage implements ITimeRange { | |
54 | ||
df0b8ff4 BH |
55 | // ------------------------------------------------------------------------ |
56 | // Constants | |
57 | // ------------------------------------------------------------------------ | |
58 | /** | |
59 | * The grahNode ID constant | |
60 | */ | |
61 | public static final String ASYNC_MESS_TAG = "AsyncMessage"; //$NON-NLS-1$ | |
62 | ||
63 | // ------------------------------------------------------------------------ | |
64 | // Attributes | |
65 | // ------------------------------------------------------------------------ | |
66 | /** | |
67 | * Flag whether message has time information or not. | |
68 | */ | |
cab6c8ff | 69 | private boolean fHasTime = false; |
73005152 BH |
70 | /** |
71 | * The time when the message begin | |
72 | */ | |
cab6c8ff | 73 | private ITmfTimestamp fEndTime = new TmfTimestamp(); |
73005152 BH |
74 | /** |
75 | * The time when the message end | |
76 | */ | |
cab6c8ff | 77 | private ITmfTimestamp fStartTime = new TmfTimestamp(); |
73005152 BH |
78 | /** |
79 | * The associated message. | |
80 | */ | |
eb63f5ff | 81 | protected AsyncMessageReturn fMessageReturn = null; |
73005152 | 82 | |
df0b8ff4 BH |
83 | // ------------------------------------------------------------------------ |
84 | // Constructors | |
85 | // ------------------------------------------------------------------------ | |
86 | /** | |
87 | * Default constructor | |
88 | */ | |
73005152 | 89 | public AsyncMessage() { |
cab6c8ff | 90 | setColorPrefId(ISDPreferences.PREF_ASYNC_MESS); |
73005152 BH |
91 | } |
92 | ||
df0b8ff4 BH |
93 | // ------------------------------------------------------------------------ |
94 | // Methods | |
95 | // ------------------------------------------------------------------------ | |
11252342 | 96 | |
73005152 BH |
97 | @Override |
98 | public int getX() { | |
99 | int x = super.getX(true); | |
100 | int activationWidth = Metrics.EXECUTION_OCCURRENCE_WIDTH / 2; | |
cab6c8ff | 101 | if ((getStartLifeline() != null) && (getEndLifeline() != null) && (getStartLifeline().getX() > getEndLifeline().getX())) { |
73005152 BH |
102 | activationWidth = -activationWidth; |
103 | } | |
104 | ||
cab6c8ff | 105 | if (isMessageStartInActivation(getStartOccurrence())) { |
73005152 BH |
106 | x = x + activationWidth; |
107 | } | |
108 | return x; | |
109 | } | |
013a5f1c | 110 | |
73005152 BH |
111 | @Override |
112 | public int getY() { | |
cab6c8ff BH |
113 | if ((getStartLifeline() != null) && (getEndLifeline() != null)) { |
114 | return getEndLifeline().getY() + getEndLifeline().getHeight() + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * getStartOccurrence(); | |
73005152 BH |
115 | } |
116 | return super.getY(); | |
117 | } | |
118 | ||
119 | @Override | |
120 | public int getWidth() { | |
121 | int width = super.getWidth(true); | |
122 | int activationWidth = Metrics.EXECUTION_OCCURRENCE_WIDTH / 2; | |
cab6c8ff | 123 | if ((getStartLifeline() != null) && (getEndLifeline() != null) && (getStartLifeline().getX() > getEndLifeline().getX())) { |
73005152 BH |
124 | activationWidth = -activationWidth; |
125 | } | |
126 | ||
cab6c8ff | 127 | if (isMessageStartInActivation(getStartOccurrence())) { |
73005152 | 128 | width = width - activationWidth; |
df0b8ff4 | 129 | } |
73005152 | 130 | |
cab6c8ff | 131 | if (isMessageEndInActivation(getEndOccurrence())) { |
73005152 | 132 | width = width - activationWidth; |
df0b8ff4 | 133 | } |
73005152 BH |
134 | |
135 | return width; | |
136 | } | |
137 | ||
138 | @Override | |
139 | public int getHeight() { | |
cab6c8ff BH |
140 | if ((getStartLifeline() != null) && (getEndLifeline() != null)) { |
141 | return (getEndLifeline().getY() + getEndLifeline().getHeight() + (Metrics.getMessageFontHeigth() + Metrics.getMessagesSpacing()) * getEndOccurrence()) - getY(); | |
73005152 BH |
142 | } |
143 | return super.getHeight(); | |
144 | } | |
145 | ||
146 | /** | |
147 | * Set the message return associated with this message. | |
013a5f1c | 148 | * |
73005152 BH |
149 | * @param message the message return to associate |
150 | */ | |
151 | protected void setMessageReturn(AsyncMessageReturn message) { | |
eb63f5ff | 152 | fMessageReturn = message; |
73005152 BH |
153 | } |
154 | ||
155 | /** | |
156 | * Set the event occurrence attached to this message for its end lifeline | |
013a5f1c | 157 | * |
73005152 BH |
158 | * @param occurrence the event occurrence to set |
159 | */ | |
cab6c8ff | 160 | @Override |
73005152 | 161 | public void setEndOccurrence(int occurrence) { |
cab6c8ff | 162 | super.setEndOccurrence(occurrence); |
df0b8ff4 | 163 | if (getStartLifeline() == null) { |
cab6c8ff | 164 | setStartOccurrence(occurrence); |
df0b8ff4 | 165 | } |
73005152 BH |
166 | informFrame(getEndLifeline(), occurrence); |
167 | } | |
168 | ||
df0b8ff4 BH |
169 | /** |
170 | * Informs the given lifeline about the maximum occurrence if applicable. | |
013a5f1c | 171 | * |
df0b8ff4 | 172 | * @param lifeLine |
a0a88f65 | 173 | * Concerned lifeline |
df0b8ff4 | 174 | * @param occurrence |
a0a88f65 | 175 | * Occurrence number |
df0b8ff4 | 176 | */ |
73005152 | 177 | protected void informFrame(Lifeline lifeLine, int occurrence) { |
df0b8ff4 BH |
178 | if ((lifeLine != null) && (lifeLine.getFrame() != null) && (lifeLine.getFrame().getMaxEventOccurrence() < occurrence)) { |
179 | lifeLine.getFrame().setMaxEventOccurrence(occurrence); | |
180 | } | |
73005152 BH |
181 | } |
182 | ||
183 | /** | |
184 | * Set the event occurrence attached to this message for its start lifeline | |
013a5f1c | 185 | * |
73005152 BH |
186 | * @param occurrence the event occurrence to set |
187 | */ | |
cab6c8ff | 188 | @Override |
73005152 | 189 | public void setStartOccurrence(int occurrence) { |
cab6c8ff | 190 | super.setStartOccurrence(occurrence); |
df0b8ff4 | 191 | if (getEndLifeline() == null) { |
cab6c8ff | 192 | setEndOccurrence(getStartOccurrence()); |
df0b8ff4 | 193 | } |
73005152 BH |
194 | informFrame(getStartLifeline(), occurrence); |
195 | } | |
196 | ||
197 | /** | |
198 | * Set the lifeLine which has sent the message.<br> | |
199 | * A new EventOccurence will be create on this lifeLine.<br> | |
013a5f1c | 200 | * |
73005152 | 201 | * @param lifeline the message sender |
73005152 BH |
202 | */ |
203 | public void autoSetStartLifeline(Lifeline lifeline) { | |
204 | lifeline.getNewEventOccurrence(); | |
205 | setStartLifeline(lifeline); | |
206 | } | |
207 | ||
208 | /** | |
209 | * Set the lifeLine which has received the message.<br> | |
210 | * A new EventOccurence will be create on this lifeLine.<br> | |
013a5f1c | 211 | * |
73005152 | 212 | * @param lifeline the message receiver |
73005152 BH |
213 | */ |
214 | public void autoSetEndLifeline(Lifeline lifeline) { | |
215 | lifeline.getNewEventOccurrence(); | |
216 | setEndLifeline(lifeline); | |
217 | } | |
218 | ||
73005152 BH |
219 | @Override |
220 | public void setStartLifeline(Lifeline lifeline) { | |
221 | super.setStartLifeline(lifeline); | |
222 | setStartOccurrence(getStartLifeline().getEventOccurrence()); | |
df0b8ff4 | 223 | if (getEndLifeline() == null) { |
cab6c8ff | 224 | setEndOccurrence(getStartOccurrence()); |
df0b8ff4 | 225 | } |
73005152 BH |
226 | } |
227 | ||
73005152 BH |
228 | @Override |
229 | public void setEndLifeline(Lifeline lifeline) { | |
230 | super.setEndLifeline(lifeline); | |
231 | setEventOccurrence(getEndLifeline().getEventOccurrence()); | |
232 | } | |
233 | ||
234 | /** | |
235 | * Returns true if the point C is on the segment defined with the point A and B | |
013a5f1c | 236 | * |
73005152 BH |
237 | * @param xA point A x coordinate |
238 | * @param yA point A y coordinate | |
239 | * @param xB point B x coordinate | |
240 | * @param yB point B y coordinate | |
241 | * @param xC point C x coordinate | |
242 | * @param yC point C y coordinate | |
243 | * @return Return true if the point C is on the segment defined with the point A and B, else otherwise | |
244 | */ | |
245 | protected boolean isNearSegment(int xA, int yA, int xB, int yB, int xC, int yC) { | |
df0b8ff4 | 246 | if ((xA > xB) && (xC > xA)) { |
73005152 | 247 | return false; |
df0b8ff4 BH |
248 | } |
249 | if ((xA < xB) && (xC > xB)) { | |
73005152 | 250 | return false; |
df0b8ff4 BH |
251 | } |
252 | if ((xA < xB) && (xC < xA)) { | |
73005152 | 253 | return false; |
df0b8ff4 BH |
254 | } |
255 | if ((xA > xB) && (xC < xB)) { | |
73005152 | 256 | return false; |
df0b8ff4 | 257 | } |
73005152 BH |
258 | double distAB = Math.sqrt((xB - xA) * (xB - xA) + (yB - yA) * (yB - yA)); |
259 | double scalar = ((xB - xA) * (xC - xA) + (yB - yA) * (yC - yA)) / distAB; | |
260 | double distAC = Math.sqrt((xC - xA) * (xC - xA) + (yC - yA) * (yC - yA)); | |
261 | double distToSegment = Math.sqrt(Math.abs(distAC * distAC - scalar * scalar)); | |
df0b8ff4 | 262 | if (distToSegment <= Metrics.MESSAGE_SELECTION_TOLERANCE) { |
73005152 | 263 | return true; |
df0b8ff4 | 264 | } |
73005152 BH |
265 | return false; |
266 | } | |
267 | ||
268 | @Override | |
269 | public boolean contains(int x, int y) { | |
270 | // Is it a self message? | |
cab6c8ff | 271 | if (getStartLifeline() == getEndLifeline()) { |
73005152 BH |
272 | return super.contains(x, y); |
273 | } | |
013a5f1c | 274 | if (isNearSegment(getX(), getY(), getX() + getWidth(), getY() + getHeight(), x, y)) { |
73005152 | 275 | return true; |
013a5f1c | 276 | } |
73005152 BH |
277 | int messageMaxWidth = Metrics.swimmingLaneWidth() - Metrics.EXECUTION_OCCURRENCE_WIDTH; |
278 | int nameWidth = getName().length() * Metrics.getAverageCharWidth(); | |
279 | if (getName().length() * Metrics.getAverageCharWidth() > messageMaxWidth) { | |
abbdd66a | 280 | if (GraphNode.contains(getX(), getY() - Metrics.MESSAGES_NAME_SPACING - Metrics.getMessageFontHeigth(), messageMaxWidth, Metrics.getMessageFontHeigth(), x, y)) { |
73005152 | 281 | return true; |
df0b8ff4 | 282 | } |
73005152 | 283 | } else { |
abbdd66a | 284 | if (GraphNode.contains(getX() + (messageMaxWidth - nameWidth) / 2, getY() + getHeight() / 2 - Metrics.MESSAGES_NAME_SPACING - Metrics.getMessageFontHeigth(), nameWidth, Metrics.getMessageFontHeigth(), x, y)) { |
73005152 | 285 | return true; |
df0b8ff4 | 286 | } |
73005152 BH |
287 | } |
288 | return false; | |
289 | } | |
290 | ||
df0b8ff4 BH |
291 | /** |
292 | * Draws the asynchronous message using giving graphical context. | |
013a5f1c | 293 | * |
df0b8ff4 BH |
294 | * @param context A graphical context to draw in. |
295 | */ | |
73005152 | 296 | protected void drawAsyncMessage(IGC context) { |
cab6c8ff | 297 | if (getStartLifeline() != null && getEndLifeline() != null && getStartLifeline() == getEndLifeline() && (getStartOccurrence() != getEndOccurrence())) { |
73005152 BH |
298 | int x = getX(); |
299 | int y = getY(); | |
300 | int height = getHeight(); | |
301 | int tempx = 0; | |
cab6c8ff BH |
302 | boolean startInActivation = isMessageStartInActivation(getStartOccurrence()); |
303 | boolean endInActivation = isMessageEndInActivation(getEndOccurrence()); | |
73005152 | 304 | |
df0b8ff4 | 305 | if (endInActivation && !startInActivation) { |
73005152 | 306 | tempx = Metrics.EXECUTION_OCCURRENCE_WIDTH / 2; |
df0b8ff4 BH |
307 | } |
308 | if (startInActivation && !endInActivation) { | |
73005152 | 309 | tempx = -Metrics.EXECUTION_OCCURRENCE_WIDTH / 2; |
df0b8ff4 | 310 | } |
73005152 BH |
311 | |
312 | int tempy = Metrics.INTERNAL_MESSAGE_WIDTH / 2; | |
df0b8ff4 | 313 | if (getHeight() <= Metrics.INTERNAL_MESSAGE_WIDTH) { |
73005152 | 314 | tempy = getHeight() / 2; |
df0b8ff4 | 315 | } |
73005152 BH |
316 | |
317 | context.drawLine(x, y, x + Metrics.INTERNAL_MESSAGE_WIDTH / 2, y); | |
318 | context.drawLine(x + Metrics.INTERNAL_MESSAGE_WIDTH, y + tempy, x + Metrics.INTERNAL_MESSAGE_WIDTH, y + height - tempy); | |
319 | context.drawLine(x + tempx, y + height, x + Metrics.INTERNAL_MESSAGE_WIDTH / 2, y + height); | |
320 | ||
eb63f5ff BH |
321 | Double xt = Double.valueOf(Math.cos(0.75) * 7); |
322 | Double yt = Double.valueOf(Math.sin(0.75) * 7); | |
73005152 BH |
323 | |
324 | context.drawLine(x + xt.intValue() + tempx, y + height + yt.intValue(), x + tempx, y + height); | |
325 | context.drawArc(x, y, Metrics.INTERNAL_MESSAGE_WIDTH, 2 * tempy, 0, 90); | |
326 | context.drawArc(x, y + height, Metrics.INTERNAL_MESSAGE_WIDTH, -2 * tempy, 0, -90); | |
327 | context.drawLine(x + xt.intValue() + tempx, y + height - yt.intValue(), x + tempx, y + height); | |
328 | ||
329 | context.drawTextTruncated(getName(), x + Metrics.INTERNAL_MESSAGE_WIDTH + Metrics.INTERNAL_MESSAGE_V_MARGIN, y, Metrics.swimmingLaneWidth() - Metrics.EXECUTION_OCCURRENCE_WIDTH + -Metrics.INTERNAL_MESSAGE_WIDTH, | |
330 | +Metrics.MESSAGES_NAME_SPACING - Metrics.getMessageFontHeigth(), !isSelected()); | |
df0b8ff4 | 331 | } else { |
73005152 | 332 | super.draw(context); |
df0b8ff4 | 333 | } |
73005152 BH |
334 | } |
335 | ||
73005152 BH |
336 | @Override |
337 | public void draw(IGC context) { | |
df0b8ff4 | 338 | if (!isVisible()) { |
73005152 | 339 | return; |
df0b8ff4 | 340 | } |
3145ec83 BH |
341 | |
342 | ISDPreferences pref = SDViewPref.getInstance(); | |
343 | ||
73005152 | 344 | // Draw it selected? |
cab6c8ff | 345 | if (isSelected() && (getStartLifeline() != null && getEndLifeline() != null && getStartLifeline() == getEndLifeline() && (getStartOccurrence() != getEndOccurrence()))) { |
73005152 BH |
346 | /* |
347 | * Draw it twice First time, bigger inverting selection colors Second time, regular drawing using selection | |
348 | * colors This create the highlight effect | |
349 | */ | |
3145ec83 | 350 | context.setForeground(pref.getBackGroundColorSelection()); |
73005152 BH |
351 | context.setLineWidth(Metrics.SELECTION_LINE_WIDTH); |
352 | drawAsyncMessage(context); | |
3145ec83 BH |
353 | context.setBackground(pref.getBackGroundColorSelection()); |
354 | context.setForeground(pref.getForeGroundColorSelection()); | |
73005152 BH |
355 | // Second drawing is done after the else |
356 | } else { | |
cab6c8ff BH |
357 | context.setBackground(pref.getBackGroundColor(getColorPrefId())); |
358 | context.setForeground(pref.getForeGroundColor(getColorPrefId())); | |
73005152 BH |
359 | } |
360 | if (hasFocus()) { | |
361 | context.setDrawTextWithFocusStyle(true); | |
362 | } | |
363 | context.setLineWidth(Metrics.NORMAL_LINE_WIDTH); | |
364 | drawAsyncMessage(context); | |
365 | if (hasFocus()) { | |
366 | context.setDrawTextWithFocusStyle(false); | |
367 | } | |
368 | } | |
369 | ||
370 | /** | |
371 | * Set the time when the message end | |
013a5f1c | 372 | * |
73005152 BH |
373 | * @param time the time when the message end |
374 | */ | |
4df4581d | 375 | public void setEndTime(ITmfTimestamp time) { |
4593bd5b | 376 | fEndTime = time; |
eb63f5ff | 377 | fHasTime = true; |
df0b8ff4 | 378 | if (getStartLifeline() != null && getStartLifeline().getFrame() != null) { |
73005152 | 379 | getStartLifeline().getFrame().setHasTimeInfo(true); |
df0b8ff4 | 380 | } else if (getEndLifeline() != null && getEndLifeline().getFrame() != null) { |
73005152 | 381 | getEndLifeline().getFrame().setHasTimeInfo(true); |
df0b8ff4 | 382 | } |
73005152 BH |
383 | } |
384 | ||
385 | /** | |
386 | * Set the time when the message start | |
013a5f1c | 387 | * |
73005152 BH |
388 | * @param time the time when the message start |
389 | */ | |
4df4581d | 390 | public void setStartTime(ITmfTimestamp time) { |
4593bd5b | 391 | fStartTime = time; |
eb63f5ff | 392 | fHasTime = true; |
df0b8ff4 | 393 | if (getStartLifeline() != null && getStartLifeline().getFrame() != null) { |
73005152 | 394 | getStartLifeline().getFrame().setHasTimeInfo(true); |
df0b8ff4 | 395 | } else if (getEndLifeline() != null && getEndLifeline().getFrame() != null) { |
73005152 | 396 | getEndLifeline().getFrame().setHasTimeInfo(true); |
df0b8ff4 | 397 | } |
73005152 BH |
398 | } |
399 | ||
73005152 | 400 | @Override |
4df4581d | 401 | public ITmfTimestamp getEndTime() { |
eb63f5ff | 402 | return fEndTime; |
73005152 BH |
403 | } |
404 | ||
73005152 | 405 | @Override |
4df4581d | 406 | public ITmfTimestamp getStartTime() { |
eb63f5ff | 407 | return fStartTime; |
73005152 BH |
408 | } |
409 | ||
410 | @Override | |
411 | public boolean hasTimeInfo() { | |
eb63f5ff | 412 | return fHasTime; |
73005152 BH |
413 | } |
414 | ||
cab6c8ff BH |
415 | /** |
416 | * @return message return instance or null | |
cab6c8ff BH |
417 | */ |
418 | public AsyncMessageReturn getMessageReturn() { | |
419 | return fMessageReturn; | |
420 | } | |
421 | ||
73005152 BH |
422 | @Override |
423 | public boolean isVisible(int x, int y, int width, int height) { | |
424 | int toDrawY = getY(); | |
425 | int toDrawHeight = getHeight(); | |
df0b8ff4 | 426 | if ((toDrawY > y + height + Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth()) && (toDrawY + toDrawHeight > y + height + Metrics.MESSAGES_NAME_SPACING + Metrics.getMessageFontHeigth())) { |
73005152 | 427 | return false; |
df0b8ff4 BH |
428 | } |
429 | if (toDrawY < y && (toDrawY + toDrawHeight < y)) { | |
73005152 | 430 | return false; |
df0b8ff4 | 431 | } |
73005152 BH |
432 | return super.isVisible(x, y, width, height); |
433 | } | |
434 | ||
435 | @Override | |
436 | public Comparator<GraphNode> getComparator() { | |
437 | return new SortAsyncMessageComparator(); | |
438 | } | |
439 | ||
440 | @Override | |
441 | public String getArrayId() { | |
442 | return ASYNC_MESS_TAG; | |
443 | } | |
444 | ||
445 | @Override | |
446 | public Comparator<GraphNode> getBackComparator() { | |
447 | return new SortAsyncForBackward(); | |
448 | } | |
449 | ||
450 | @Override | |
451 | public boolean positiveDistanceToPoint(int x, int y) { | |
452 | int mY = getY(); | |
453 | int mH = getHeight(); | |
df0b8ff4 | 454 | if ((mY > y) || (mY + mH > y)) { |
73005152 | 455 | return true; |
df0b8ff4 | 456 | } |
73005152 BH |
457 | return false; |
458 | } | |
459 | } |