· 5 years ago · Oct 06, 2020, 10:18 AM
1//
2// -Changes no assigned groups to mean "all" geozones. [2.6.6-B38]
3// ----------------------------------------------------------------------------
4package org.fmsbce.war.track.page;
5
6import java.util.*;
7import java.io.*;
8
9import javax.servlet.*;
10import javax.servlet.http.*;
11
12import org.fmsbce.util.*;
13import org.fmsbce.dbtools.*;
14import org.fmsbce.db.*;
15import org.fmsbce.db.tables.*;
16import org.fmsbce.geocoder.GeocodeProvider;
17
18import org.fmsbce.war.tools.*;
19import org.fmsbce.war.track.*;
20
21public class ZoneInfo
22 extends WebPageAdaptor
23 implements Constants
24{
25
26 // ------------------------------------------------------------------------
27 // 'private.xml' properties
28
29 // PrivateLabel.PROP_ZoneInfo_mapControlLocation
30 private static final String CONTROLS_ON_LEFT[] = new String[] { "left", "true" };
31
32 // ------------------------------------------------------------------------
33
34 private static final double DEFAULT_ZONE_RADIUS = 20000.0;
35
36 // ------------------------------------------------------------------------
37
38 private static final String OVERLAP_PRIORITY[] = new String[] { "0", "1", "2", "3", "4", "5" };
39
40 // ------------------------------------------------------------------------
41 // Parameters
42
43 // forms
44 public static final String FORM_ZONE_SELECT = "ZoneInfoSelect";
45 public static final String FORM_ZONE_EDIT = "ZoneInfoEdit";
46 public static final String FORM_ZONE_NEW = "ZoneInfoNew";
47
48 // commands
49 public static final String COMMAND_INFO_UPDATE = "update";
50 public static final String COMMAND_INFO_SELECT = "select";
51 public static final String COMMAND_INFO_NEW = "new";
52
53 // submit
54 public static final String PARM_SUBMIT_EDIT = "z_subedit";
55 public static final String PARM_SUBMIT_VIEW = "z_subview";
56 public static final String PARM_SUBMIT_CHG = "z_subchg";
57 public static final String PARM_SUBMIT_DEL = "z_subdel";
58 public static final String PARM_SUBMIT_NEW = "z_subnew";
59
60 // buttons
61 public static final String PARM_BUTTON_CANCEL = "u_btncan";
62 public static final String PARM_BUTTON_BACK = "u_btnbak";
63
64 // parameters
65 public static final String PARM_NEW_ID = "z_newid";
66 public static final String PARM_NEW_TYPE = "z_newtype";
67
68 // parameters
69 public static final String PARM_ZONE_SELECT = "z_zone";
70 public static final String PARM_ZONE_ACTIVE = "z_actv";
71 public static final String PARM_PRIORITY = "z_priority";
72 public static final String PARM_REV_GEOCODE = "z_revgeo";
73 public static final String PARM_ARRIVE_NOTIFY = "z_arrive";
74 public static final String PARM_ARRIVE_CODE = "z_arrcode";
75 public static final String PARM_DEPART_NOTIFY = "z_depart";
76 public static final String PARM_DEPART_CODE = "z_depcode";
77 public static final String PARM_AUTO_NOTIFY = "z_autontfy";
78 public static final String PARM_CLIENT_UPLOAD = "z_upload";
79 public static final String PARM_CLIENT_ID = "z_clntid";
80 public static final String PARM_SPEED_LIMIT = "z_spdlim";
81 public static final String PARM_PURPOSE_ID = "z_purpid";
82 public static final String PARM_CORRIDOR_ID = "z_corrid";
83 public static final String PARM_GROUP_SELECT = "z_group";
84
85 public static final String PARM_ZONE_DESC = "z_desc";
86 public static final String PARM_ZONE_RADIUS = "z_radius";
87 public static final String PARM_ZONE_INDEX = "z_index";
88 public static final String PARM_ZONE_COLOR = "z_color";
89 public static final String PARM_ZONE_PUSHPIN = "z_ppin";
90
91 public static final String PARM_ZONE_LATITUDE_ = "z_lat";
92 private static String PARM_ZONE_LATITUDE(int ndx)
93 {
94 return PARM_ZONE_LATITUDE_ + ndx;
95 }
96 public static final String PARM_ZONE_LONGITUDE_ = "z_lon";
97 public static final String PARM_ZONE_LONGITUDE(int ndx)
98 {
99 return PARM_ZONE_LONGITUDE_ + ndx;
100 }
101
102 // sort ID
103 private static final int DEFAULT_SORT_ID = 0;
104
105 // point index
106 private static final int DEFAULT_POINT_INDEX = 0;
107
108 // ------------------------------------------------------------------------
109 // ------------------------------------------------------------------------
110
111 /* possible options for arrive/depart status codes */
112 private static int STATUS_CODES[][] = {
113 // ArrivalCodes DepartureCodes
114 { StatusCodes.STATUS_GEOFENCE_ARRIVE, StatusCodes.STATUS_GEOFENCE_DEPART },
115 { StatusCodes.STATUS_GEOFENCE_ACTIVE, StatusCodes.STATUS_GEOFENCE_INACTIVE },
116 { StatusCodes.STATUS_GEOBOUNDS_ENTER, StatusCodes.STATUS_GEOBOUNDS_EXIT },
117 { StatusCodes.STATUS_JOB_ARRIVE , StatusCodes.STATUS_JOB_DEPART },
118 { StatusCodes.STATUS_JOB_START , StatusCodes.STATUS_JOB_STOP },
119 { StatusCodes.STATUS_JOB_STOP , StatusCodes.STATUS_JOB_START },
120 { StatusCodes.STATUS_TRACK_START , StatusCodes.STATUS_TRACK_STOP },
121 { StatusCodes.STATUS_TRACK_STOP , StatusCodes.STATUS_TRACK_START },
122 { StatusCodes.STATUS_DUTY_ON , StatusCodes.STATUS_DUTY_OFF },
123 { StatusCodes.STATUS_DUTY_OFF , StatusCodes.STATUS_DUTY_ON },
124 { StatusCodes.STATUS_INTRUSION_ON , StatusCodes.STATUS_INTRUSION_OFF },
125 //{ StatusCodes.STATUS_BREACH_ON , StatusCodes.STATUS_BREACH_OFF },
126 //{ StatusCodes.STATUS_CORRIDOR_ARRIVE, StatusCodes.STATUS_CORRIDOR_DEPART },
127 //{ StatusCodes.STATUS_CORRIDOR_ACTIVE, StatusCodes.STATUS_CORRIDOR_INACTIVE },
128 //{ StatusCodes.STATUS_PERSON_ENTER , StatusCodes.STATUS_PERSON_EXIT },
129 };
130
131 private static ComboMap getArrivalCodeComboMap(BasicPrivateLabel bpl)
132 {
133 return ZoneInfo._getStatusCodeComboMap(0/*arrive*/, bpl);
134 }
135
136 private static ComboMap getDepartureCodeComboMap(BasicPrivateLabel bpl)
137 {
138 return ZoneInfo._getStatusCodeComboMap(1/*depart*/, bpl);
139 }
140
141 private static ComboMap _getStatusCodeComboMap(int scNdx, BasicPrivateLabel bpl)
142 {
143 ComboMap scList = new ComboMap();
144 for (int sca[] : STATUS_CODES) {
145 int sc = sca[(scNdx <= 0)? 0 : 1];
146 String key = "0x"+StringTools.toHexString(sc,16);
147 String desc = StatusCodes.GetDescription(sc,bpl);
148 scList.add(key, desc);
149 }
150 return scList;
151 }
152
153 // ------------------------------------------------------------------------
154 // ------------------------------------------------------------------------
155 // WebPage interface
156
157 public ZoneInfo()
158 {
159 this.setBaseURI(RequestProperties.TRACK_BASE_URI());
160 this.setPageName(PAGE_ZONE_INFO);
161 this.setPageNavigation(new String[] { PAGE_LOGIN, PAGE_MENU_TOP });
162 this.setLoginRequired(true);
163 }
164
165 // ------------------------------------------------------------------------
166
167 public String getMenuName(RequestProperties reqState)
168 {
169 return MenuBar.MENU_ADMIN;
170 }
171
172 public String getMenuDescription(RequestProperties reqState, String parentMenuName)
173 {
174 PrivateLabel privLabel = reqState.getPrivateLabel();
175 I18N i18n = privLabel.getI18N(ZoneInfo.class);
176 return super._getMenuDescription(reqState,i18n.getString("ZoneInfo.editMenuDesc","View/Edit Geozone Information"));
177 }
178
179 public String getMenuHelp(RequestProperties reqState, String parentMenuName)
180 {
181 PrivateLabel privLabel = reqState.getPrivateLabel();
182 I18N i18n = privLabel.getI18N(ZoneInfo.class);
183 return super._getMenuHelp(reqState,i18n.getString("ZoneInfo.editMenuHelp","View and Edit Geozone information"));
184 }
185
186 // ------------------------------------------------------------------------
187
188 public String getNavigationDescription(RequestProperties reqState)
189 {
190 PrivateLabel privLabel = reqState.getPrivateLabel();
191 I18N i18n = privLabel.getI18N(ZoneInfo.class);
192 return super._getNavigationDescription(reqState,i18n.getString("ZoneInfo.navDesc","Geozone"));
193 }
194
195 public String getNavigationTab(RequestProperties reqState)
196 {
197 PrivateLabel privLabel = reqState.getPrivateLabel();
198 I18N i18n = privLabel.getI18N(ZoneInfo.class);
199 return super._getNavigationTab(reqState,i18n.getString("ZoneInfo.navTab","Geozone Admin"));
200 }
201
202 // ------------------------------------------------------------------------
203
204 private static int parseClientUploadFlag(PrivateLabel privLabel)
205 {
206 String uplFlag = privLabel.getStringProperty(PrivateLabel.PROP_ZoneInfo_showClientUploadZone,"");
207 if (StringTools.isBlank(uplFlag)) {
208 return 0; // do not show
209 } else
210 if (uplFlag.equalsIgnoreCase("false")) {
211 return 0; // do not show
212 } else
213 if (uplFlag.equalsIgnoreCase("true") || uplFlag.equalsIgnoreCase("checkbox")) {
214 return 1; // show checkbox only
215 } else
216 if (uplFlag.equalsIgnoreCase("id")) {
217 return 2; // show id field only
218 } else {
219 return 0;
220 }
221 }
222
223 private static ComboMap GetColorComboMap(I18N i18n)
224 {
225 ComboMap cc = new ComboMap();
226 cc.add("" ,i18n.getString("ZoneInfo.color.default","Default"));
227 cc.add(ColorTools.BLACK.toString(true) ,i18n.getString("ZoneInfo.color.black" ,"Black" ));
228 cc.add(ColorTools.BROWN.toString(true) ,i18n.getString("ZoneInfo.color.brown" ,"Brown" ));
229 cc.add(ColorTools.RED.toString(true) ,i18n.getString("ZoneInfo.color.red" ,"Red" ));
230 cc.add(ColorTools.ORANGE.toString(true) ,i18n.getString("ZoneInfo.color.orange" ,"Orange" ));
231 cc.add(ColorTools.YELLOW.toString(true) ,i18n.getString("ZoneInfo.color.yellow" ,"Yellow" ));
232 cc.add(ColorTools.GREEN.toString(true) ,i18n.getString("ZoneInfo.color.green" ,"Green" ));
233 cc.add(ColorTools.BLUE.toString(true) ,i18n.getString("ZoneInfo.color.blue" ,"Blue" ));
234 cc.add(ColorTools.PURPLE.toString(true) ,i18n.getString("ZoneInfo.color.purple" ,"Purple" ));
235 cc.add(ColorTools.DARK_GRAY.toString(true) ,i18n.getString("ZoneInfo.color.gray" ,"Gray" ));
236 cc.add(ColorTools.WHITE.toString(true) ,i18n.getString("ZoneInfo.color.white" ,"White" ));
237 cc.add(ColorTools.CYAN.toString(true) ,i18n.getString("ZoneInfo.color.cyan" ,"Cyan" ));
238 cc.add(ColorTools.PINK.toString(true) ,i18n.getString("ZoneInfo.color.pink" ,"Pink" ));
239 return cc;
240 }
241
242 private static ComboMap GetPushpinComboMap(I18N i18n, RequestProperties reqState)
243 {
244 ComboMap cc = new ComboMap();
245 cc.add("",i18n.getString("ZoneInfo.pushpin.default","None"));
246 MapProvider mapProv = reqState.getMapProvider();
247 if (mapProv != null) {
248 Map<String,PushpinIcon> ppMap = mapProv.getPushpinIconMap(reqState);
249 for (String ppID : ppMap.keySet()) {
250 PushpinIcon ppIcon = ppMap.get(ppID);
251 if (ppIcon.getIconEval()) {
252 // -- skip pushpins that require evaluation
253 continue;
254 }
255 cc.add(ppID,ppID);
256 }
257 }
258 return cc;
259 }
260
261 private static int getGeozoneSupportedPointCount(RequestProperties reqState, int type)
262 {
263 PrivateLabel privLabel = reqState.getPrivateLabel(); // never null
264 MapProvider mapProvider = reqState.getMapProvider(); // may be null
265 int pointCount = (mapProvider != null)? mapProvider.getGeozoneSupportedPointCount(type) : 0;
266 int maxCount = privLabel.getIntProperty(PrivateLabel.PROP_ZoneInfo_maximumDisplayedVertices, -1);
267 if ((maxCount > 0) && (pointCount > maxCount)) {
268 pointCount = maxCount;
269 }
270 return pointCount;
271 }
272
273 private static String[] getGeozoneIDs(PrivateLabel privLabel, Account currAcct, User currUser)
274 {
275 DBReadWriteMode rwMode = DBReadWriteMode.READ_WRITE;
276 String acctID = currAcct.getAccountID();
277 String userID = (currUser != null)? currUser.getUserID() : User.getAdminUserID();
278 try {
279
280 // -- limit displayed Geozones?
281 boolean limitToGroups = privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_limitToUserDeviceGroups,false);
282 if (limitToGroups && !User.isAdminUser(userID)) {
283 // -- return only geozones that match the current users authorized groups
284 java.util.List<String> dgList = User.getExplicitlyAuthorizedDeviceGroupIDs(rwMode, acctID, userID, -1L);
285 if (ListTools.isEmpty(dgList)) {
286 // -- no DeviceGroups assigned to user (none is all? [2.6.6-B38])
287 //return new String[0]; <== removed [2.6.6-B38]
288 return Geozone.getGeozoneIDsForAccount(rwMode, currAcct, currUser, (String[])null); // has Account/User
289 } else {
290 // -- get Geozones assigned to a the users DeviceGroup
291 String dgIDs[] = dgList.toArray(new String[dgList.size()]);
292 return Geozone.getGeozoneIDsForAccount(rwMode, currAcct, currUser, dgIDs); // has Account/User
293 }
294 }
295
296 // -- no Geozone limits, get all Geozones
297 return Geozone.getGeozoneIDsForAccount(rwMode, currAcct, currUser, (String[])null); // has Account/User
298
299 } catch (DBException dbe) {
300
301 // -- error, return no geozones
302 Print.logError("[Error] Returning no Geozones: " + dbe);
303 return new String[0];
304
305 }
306 }
307
308 public void writePage(
309 final RequestProperties reqState,
310 String pageMsg)
311 throws IOException
312 {
313 final HttpServletRequest request = reqState.getHttpServletRequest();
314 final PrivateLabel privLabel = reqState.getPrivateLabel(); // never null
315 final I18N i18n = privLabel.getI18N(ZoneInfo.class);
316 final Locale locale = reqState.getLocale();
317 final Account currAcct = reqState.getCurrentAccount(); // never null
318 final User currUser = reqState.getCurrentUser(); // may be null
319 final String pageName = this.getPageName();
320 final boolean showOverlapPriority = Geozone.supportsPriority() && privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_showOverlapPriority,false);
321 final boolean showSpeedLimit = Geozone.supportsSpeedLimitKPH() && privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_showSpeedLimit,false);
322 final boolean showPurposeIDs = privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_showPurposeID,false);
323 final boolean showCorridorIDs = Geozone.supportsCorridor() && privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_showCorridorID,false);
324 final boolean showRevGeocodeZone = privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_showReverseGeocodeZone,true);
325 final boolean showArriveDepartZone = Device.hasRuleFactory() || privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_showArriveDepartZone,false);
326 final boolean showArriveDepartCode = showArriveDepartZone && privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_showArriveDepartCode,false);
327 final boolean showAutoNotify = showArriveDepartZone && privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_showAutoNotify,false);
328 final int showClientUploadZone = parseClientUploadFlag(privLabel);
329 final boolean showAssignedDevGroup = privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_showAssignedDeviceGroup,false);
330 final boolean showFilter = privLabel.getBooleanProperty(PrivateLabel.PROP_AdminPage_showSearchFilter,false) && Track.jsFileExists(FILTER_JS);
331
332 String m = pageMsg;
333 boolean error = false;
334
335 /* list of geozones */
336 String zoneList[] = ZoneInfo.getGeozoneIDs(privLabel, currAcct, currUser);
337
338 /* selected geozone */
339 String selZoneID = AttributeTools.getRequestString(reqState.getHttpServletRequest(), PARM_ZONE_SELECT, "");
340 if (StringTools.isBlank(selZoneID)) {
341 if ((zoneList.length > 0) && (zoneList[0] != null)) {
342 selZoneID = zoneList[0];
343 } else {
344 selZoneID = "";
345 }
346 //Print.logWarn("No Zone selected, choosing first zone: %s", selZoneID);
347 }
348 if (zoneList.length == 0) {
349 zoneList = new String[] { selZoneID };
350 }
351
352 /* Geozone db */
353 Geozone selZone = null;
354 try {
355 selZone = !selZoneID.equals("")? Geozone.getGeozone(currAcct,selZoneID,DEFAULT_SORT_ID,false/*RGOnly*/) : null;
356 } catch (DBException dbe) {
357 // ignore
358 }
359
360 /* ACL */
361 boolean allowNew = privLabel.hasAllAccess(currUser, this.getAclName());
362 boolean allowDelete = allowNew;
363 boolean allowEdit = allowNew || privLabel.hasWriteAccess(currUser, this.getAclName());
364 boolean allowView = allowEdit || privLabel.hasReadAccess(currUser, this.getAclName());
365
366 /* command */
367 String zoneCmd = reqState.getCommandName();
368 boolean listZones = false;
369 boolean updateZone = zoneCmd.equals(COMMAND_INFO_UPDATE);
370 boolean selectZone = zoneCmd.equals(COMMAND_INFO_SELECT);
371 boolean newZone = zoneCmd.equals(COMMAND_INFO_NEW);
372 boolean deleteZone = false;
373 boolean editZone = false;
374 boolean viewZone = false;
375
376 /* submit buttons */
377 String submitEdit = AttributeTools.getRequestString(request, PARM_SUBMIT_EDIT, "");
378 String submitView = AttributeTools.getRequestString(request, PARM_SUBMIT_VIEW, "");
379 String submitChange = AttributeTools.getRequestString(request, PARM_SUBMIT_CHG , "");
380 String submitNew = AttributeTools.getRequestString(request, PARM_SUBMIT_NEW , "");
381 String submitDelete = AttributeTools.getRequestString(request, PARM_SUBMIT_DEL , "");
382
383 /* MapProvider support */
384 final MapProvider mapProvider = reqState.getMapProvider(); // check below to make sure this is not null
385 final boolean mapSupportsCursorLocation = ((mapProvider != null) && mapProvider.isFeatureSupported(MapProvider.FEATURE_LATLON_DISPLAY));
386 final boolean mapSupportsDistanceRuler = ((mapProvider != null) && mapProvider.isFeatureSupported(MapProvider.FEATURE_DISTANCE_RULER));
387 final boolean mapSupportsGeozones = ((mapProvider != null) && mapProvider.isFeatureSupported(MapProvider.FEATURE_GEOZONES));
388
389 /* sub-command */
390 String newZoneID = null;
391 int newZoneType = Geozone.GeozoneType.POINT_RADIUS.getIntValue(); // default
392 if (newZone) {
393 if (!allowNew) {
394 // not authorized to create new Geozones
395 Print.logInfo("Not authorized to create a new Geozone ...");
396 newZone = false;
397 } else {
398 HttpServletRequest httpReq = reqState.getHttpServletRequest();
399 newZoneID = AttributeTools.getRequestString(httpReq,PARM_NEW_ID,"").trim().toLowerCase();
400 newZoneType = AttributeTools.getRequestInt(httpReq,PARM_NEW_TYPE, newZoneType);
401 if (StringTools.isBlank(newZoneID)) {
402 m = i18n.getString("ZoneInfo.enterNewZone","Please enter a new Geozone name."); // UserErrMsg
403 error = true;
404 newZone = false;
405 } else
406 if (!WebPageAdaptor.isValidID(reqState,/*PrivateLabel.PROP_ZoneInfo_validateNewIDs,*/newZoneID)) {
407 m = i18n.getString("ZoneInfo.invalidIDChar","ID contains invalid characters"); // UserErrMsg
408 error = true;
409 newZone = false;
410 }
411 }
412 } else
413 if (updateZone) {
414 if (!allowEdit) {
415 // not authorized to update Geozones
416 updateZone = false;
417 } else
418 if (!SubmitMatch(submitChange,i18n.getString("ZoneInfo.change","Change"))) {
419 updateZone = false;
420 } else
421 if (selZone == null) {
422 // should not occur
423 m = i18n.getString("ZoneInfo.unableToUpdate","Unable to update Geozone, ID not found"); // UserErrMsg
424 error = true;
425 updateZone = false;
426 }
427 } else
428 if (selectZone) {
429 if (SubmitMatch(submitDelete,i18n.getString("ZoneInfo.delete","Delete"))) {
430 if (allowDelete) {
431 deleteZone = true;
432 }
433 } else
434 if (SubmitMatch(submitEdit,i18n.getString("ZoneInfo.edit","Edit"))) {
435 if (allowEdit) {
436 if (selZone == null) {
437 m = i18n.getString("ZoneInfo.pleaseSelectGeozone","Please select a Geozone"); // UserErrMsg
438 error = true;
439 listZones = true;
440 } else {
441 editZone = true;
442 viewZone = true;
443 }
444 }
445 } else
446 if (SubmitMatch(submitView,i18n.getString("ZoneInfo.view","View"))) {
447 if (allowView) {
448 if (selZone == null) {
449 m = i18n.getString("ZoneInfo.pleaseSelectGeozone","Please select a Geozone"); // UserErrMsg
450 error = true;
451 listZones = true;
452 } else {
453 viewZone = true;
454 }
455 }
456 } else {
457 listZones = true;
458 }
459 } else {
460 listZones = true;
461 }
462
463 /* delete Geozone? */
464 if (deleteZone) {
465 if (selZone == null) {
466 m = i18n.getString("ZoneInfo.pleaseSelectGeozone","Please select a Geozone"); // UserErrMsg
467 error = true;
468 } else {
469 try {
470 Geozone.Key zoneKey = (Geozone.Key)selZone.getRecordKey();
471 Print.logWarn("Deleting Geozone: " + zoneKey);
472 zoneKey.delete(true); // will also delete dependencies
473 selZoneID = "";
474 selZone = null;
475 zoneList = ZoneInfo.getGeozoneIDs(privLabel, currAcct, currUser);
476 if ((zoneList != null) && (zoneList.length > 0)) {
477 selZoneID = zoneList[0];
478 try {
479 selZone = !selZoneID.equals("")?Geozone.getGeozone(currAcct,selZoneID,DEFAULT_SORT_ID,false):null;
480 } catch (DBException dbe) {
481 // ignore
482 }
483 }
484 } catch (DBException dbe) {
485 Print.logException("Deleting Geozone", dbe);
486 m = i18n.getString("ZoneInfo.errorDelete","Internal error deleting Geozone"); // UserErrMsg
487 error = true;
488 }
489 }
490 listZones = true;
491 }
492
493 /* new Geozone? */
494 if (newZone) {
495 boolean createZoneOK = true;
496 //Print.logInfo("Creating new Geozone: %s", newZoneID);
497 for (int u = 0; u < zoneList.length; u++) {
498 if (newZoneID.equalsIgnoreCase(zoneList[u])) {
499 m = i18n.getString("ZoneInfo.alreadyExists","This Geozone already exists"); // UserErrMsg
500 error = true;
501 createZoneOK = false;
502 break;
503 }
504 }
505 if (createZoneOK) {
506 try {
507 Geozone zone = Geozone.getGeozone(currAcct, newZoneID, DEFAULT_SORT_ID, true); // create
508 zone.setZoneType(newZoneType);
509 zone.setDefaultRadius(); // based on zone type
510 zone.save(); // needs to be saved to be created
511 zoneList = ZoneInfo.getGeozoneIDs(privLabel, currAcct, currUser);
512 selZone = zone;
513 selZoneID = selZone.getGeozoneID();
514 m = i18n.getString("ZoneInfo.createdZone","New Geozone has been created"); // UserErrMsg
515 } catch (DBException dbe) {
516 Print.logException("Error Creating Geozone", dbe);
517 m = i18n.getString("ZoneInfo.errorCreate","Internal error creating Geozone"); // UserErrMsg
518 error = true;
519 }
520 }
521 listZones = true;
522 }
523
524 /* change/update the Geozone info? */
525 if (updateZone) {
526 boolean zoneActive = !StringTools.isBlank( AttributeTools.getRequestString(request,PARM_ZONE_ACTIVE,null));
527 int zonePriority = StringTools.parseInt( AttributeTools.getRequestString(request,PARM_PRIORITY,null),0);
528 boolean zoneRevGeocode = !StringTools.isBlank( AttributeTools.getRequestString(request,PARM_REV_GEOCODE,null));
529 boolean zoneArrNotify = !StringTools.isBlank( AttributeTools.getRequestString(request,PARM_ARRIVE_NOTIFY,null));
530 int zoneArrCode = StringTools.parseInt( AttributeTools.getRequestString(request,PARM_ARRIVE_CODE,null),StatusCodes.STATUS_GEOFENCE_ARRIVE);
531 boolean zoneDepNotify = !StringTools.isBlank( AttributeTools.getRequestString(request,PARM_DEPART_NOTIFY,null));
532 int zoneDepCode = StringTools.parseInt( AttributeTools.getRequestString(request,PARM_DEPART_CODE,null),StatusCodes.STATUS_GEOFENCE_DEPART);
533 boolean zoneAutoNotify = !StringTools.isBlank( AttributeTools.getRequestString(request,PARM_AUTO_NOTIFY,null));
534 boolean zoneClientUpld = !StringTools.isBlank( AttributeTools.getRequestString(request,PARM_CLIENT_UPLOAD,null));
535 int zoneClientID = StringTools.parseInt( AttributeTools.getRequestString(request,PARM_CLIENT_ID,null),0);
536 double zoneSpeedLimit = StringTools.parseDouble(AttributeTools.getRequestString(request,PARM_SPEED_LIMIT,null),0.0);
537 long zoneRadius = StringTools.parseLong( AttributeTools.getRequestString(request,PARM_ZONE_RADIUS,null),100L);
538 String zoneColor = AttributeTools.getRequestString(request,PARM_ZONE_COLOR,null);
539 String zonePushpin = AttributeTools.getRequestString(request,PARM_ZONE_PUSHPIN,null);
540 String zoneDesc = AttributeTools.getRequestString(request,PARM_ZONE_DESC,"");
541 String zonePurpID = AttributeTools.getRequestString(request,PARM_PURPOSE_ID,"");
542 String zoneCorrID = AttributeTools.getRequestString(request,PARM_CORRIDOR_ID,"");
543 String zoneGroupID = AttributeTools.getRequestString(request,PARM_GROUP_SELECT, "");
544 if (zoneGroupID.equalsIgnoreCase(DeviceGroup.DEVICE_GROUP_ALL)) { zoneGroupID = ""; }
545
546 //Print.logInfo("Updating Zone: %s - %s", selZoneID, zoneDesc);
547 try {
548 if (selZone != null) {
549 boolean saveOK = true;
550 // -- Active
551 if (!Geozone.IsGlobalActive()) {
552 // -- GlobalActive is false, set user selected active state
553 selZone.setIsActive(zoneActive);
554 } else {
555 // -- GlobalActive is true, set this zone to true as well
556 selZone.setIsActive(true);
557 }
558 // -- Overlap priority
559 if (showOverlapPriority) {
560 selZone.setPriority(zonePriority);
561 }
562 // -- Speed limit
563 if (showSpeedLimit) {
564 Account.SpeedUnits speedUnit = Account.getSpeedUnits(currAcct); // not null
565 double kph = speedUnit.convertToKPH(zoneSpeedLimit);
566 selZone.setSpeedLimitKPH(kph);
567 }
568 // -- ReverseGeocode
569 if (showRevGeocodeZone) {
570 selZone.setReverseGeocode(zoneRevGeocode);
571 } else {
572 selZone.setReverseGeocode(true);
573 }
574 // -- Arrive/Depart notification
575 if (showArriveDepartZone) {
576 selZone.setArrivalZone(zoneArrNotify);
577 selZone.setDepartureZone(zoneDepNotify);
578 if (showArriveDepartCode) {
579 int pairedDepartSC = StatusCodes.GetPairedStatusCodesMate(zoneArrCode); // [2.6.0-B49]
580 selZone.setArrivalStatusCode(zoneArrCode);
581 selZone.setDepartureStatusCode(pairedDepartSC); // zoneDepCode);
582 } else {
583 selZone.setArrivalStatusCode(StatusCodes.STATUS_GEOFENCE_ARRIVE);
584 selZone.setDepartureStatusCode(StatusCodes.STATUS_GEOFENCE_DEPART);
585 }
586 if (showAutoNotify) {
587 selZone.setAutoNotify(zoneAutoNotify);
588 } else {
589 selZone.setAutoNotify(false);
590 }
591 } else {
592 selZone.setArrivalZone(true);
593 selZone.setDepartureZone(true);
594 selZone.setArrivalStatusCode(StatusCodes.STATUS_GEOFENCE_ARRIVE);
595 selZone.setDepartureStatusCode(StatusCodes.STATUS_GEOFENCE_DEPART);
596 selZone.setAutoNotify(false);
597 }
598 // -- Client upload zone
599 if (showClientUploadZone != 0) {
600 if (zoneClientID > 0) {
601 selZone.setClientUpload(true);
602 selZone.setClientID(zoneClientID);
603 } else
604 if (zoneClientUpld) {
605 selZone.setClientUpload(true);
606 selZone.setClientID(1);
607 } else {
608 selZone.setClientUpload(false);
609 selZone.setClientID(0);
610 }
611 }
612 // -- assigned group id
613 if (!selZone.getGroupID().equalsIgnoreCase(zoneGroupID)) {
614 selZone.setGroupID(zoneGroupID);
615 }
616 // -- Radius (meters)
617 if (zoneRadius > 0L) {
618 selZone.setRadius((int)zoneRadius);
619 }
620 // -- zone color
621 if (!StringTools.isBlank(zoneColor)) {
622 selZone.setShapeColor(zoneColor);
623 }
624 // -- zone pushpin
625 if (!selZone.getIconName().equals(zonePushpin)) {
626 selZone.setIconName(zonePushpin);
627 }
628 // -- GeoPoints
629 selZone.clearGeoPoints();
630 int pointCount = ZoneInfo.getGeozoneSupportedPointCount(reqState, selZone.getZoneType());
631 Vector<GeoPoint> gpList = new Vector<GeoPoint>();
632 for (int z = 0/*, p = 0*/; z < pointCount; z++) {
633 double zoneLat = StringTools.parseDouble(AttributeTools.getRequestString(request,PARM_ZONE_LATITUDE (z),null),0.0);
634 double zoneLon = StringTools.parseDouble(AttributeTools.getRequestString(request,PARM_ZONE_LONGITUDE(z),null),0.0);
635 if (GeoPoint.isValid(zoneLat,zoneLon)) {
636 //selZone.setGeoPoint(p++, zoneLat, zoneLon);
637 gpList.add(new GeoPoint(zoneLat,zoneLon));
638 }
639 }
640 selZone.setGeoPoints(gpList);
641 // -- description
642 if (!StringTools.isBlank(zoneDesc)) {
643 selZone.setDescription(zoneDesc);
644 }
645 // -- associated Purpose ID
646 if (showPurposeIDs && !selZone.getZonePurposeID().equals(zonePurpID)) {
647 selZone.setZonePurposeID(zonePurpID);
648 }
649 // -- associated GeoCorridor ID
650 if (showCorridorIDs && !selZone.getCorridorID().equals(zoneCorrID)) {
651 selZone.setCorridorID(zoneCorrID);
652 }
653 // -- save
654 if (saveOK) {
655 selZone.save();
656 m = i18n.getString("ZoneInfo.zoneUpdated","Geozone information updated"); // UserErrMsg
657 } else {
658 // -- error occurred, should stay on this page
659 editZone = true;
660 }
661 } else {
662 m = i18n.getString("ZoneInfo.noZones","There are currently no defined Geozones for this Account."); // UserErrMsg
663 }
664 } catch (Throwable t) {
665 Print.logException("Updating Geozone", t);
666 m = i18n.getString("ZoneInfo.errorUpdate","Internal error updating Geozone"); // UserErrMsg
667 error = true;
668 }
669 listZones = true;
670 }
671
672 /* final vars */
673 final String _selZoneID = selZoneID;
674 final Geozone _selZone = selZone;
675 final String _zoneList[] = zoneList;
676 final boolean _allowEdit = allowEdit;
677 final boolean _allowView = allowView;
678 final boolean _allowNew = allowNew;
679 final boolean _allowDelete = allowDelete;
680 final boolean _editZone = _allowEdit && editZone;
681 final boolean _viewZone = _editZone || viewZone;
682 final boolean _listZones = listZones || (!_editZone && !_viewZone);
683
684 /* Style */
685 HTMLOutput HTML_CSS = new HTMLOutput() {
686 public void write(PrintWriter out) throws IOException {
687 if (mapProvider != null) {
688 mapProvider.writeStyle(out, reqState);
689 }
690 String cssDir = ZoneInfo.this.getCssDirectory();
691 WebPageAdaptor.writeCssLink(out, reqState, "ZoneInfo.css", cssDir);
692 }
693 };
694
695 /* JavaScript */
696 final boolean _showFilter = showFilter; // FILTER_JS
697 HTMLOutput HTML_JS = new HTMLOutput() {
698 public void write(PrintWriter out) throws IOException {
699 MenuBar.writeJavaScript(out, pageName, reqState);
700 JavaScriptTools.writeJSInclude(out, JavaScriptTools.qualifyJSFileRef(SORTTABLE_JS), request);
701 if (!_listZones && mapSupportsGeozones) {
702
703 // MapProvider JavaScript
704 if (mapProvider != null) {
705 mapProvider.writeJavaScript(out, reqState);
706 }
707
708 /* start JavaScript */
709 JavaScriptTools.writeStartJavaScript(out);
710
711 // Geozone Javascript
712 double radiusMeters = DEFAULT_ZONE_RADIUS;
713 int zoneTypeInt = Geozone.GeozoneType.POINT_RADIUS.getIntValue(); // default
714 String zoneColor = "";
715 if (_selZone != null) {
716 zoneTypeInt = _selZone.getZoneType();
717 zoneColor = _selZone.getShapeColor();
718 double minRad = Geozone.GetMinimumRadius(zoneTypeInt);
719 double maxRad = Geozone.GetMaximumRadius(zoneTypeInt);
720 radiusMeters = _selZone.getRadiusMeters(minRad,maxRad);
721 }
722 MapDimension mapDim = (mapProvider != null)? mapProvider.getZoneDimension() : new MapDimension(-1,-1);
723 out.println("// Geozone vars");
724 out.println("jsvGeozoneMode = true;");
725 //out.println("MAP_WIDTH = " + mapDim.getWidth() + ";");
726 //out.println("MAP_HEIGHT = " + mapDim.getHeight() + ";");
727
728 JavaScriptTools.writeJSVar(out, "DEFAULT_ZONE_RADIUS", DEFAULT_ZONE_RADIUS);
729 JavaScriptTools.writeJSVar(out, "jsvZoneEditable" , _editZone);
730 JavaScriptTools.writeJSVar(out, "jsvShowVertices" , true);
731 JavaScriptTools.writeJSVar(out, "jsvZoneType" , zoneTypeInt);
732 JavaScriptTools.writeJSVar(out, "jsvZoneRadiusMeters", radiusMeters);
733 JavaScriptTools.writeJSVar(out, "jsvZoneColor" , zoneColor);
734
735 int pointCount = ZoneInfo.getGeozoneSupportedPointCount(reqState, zoneTypeInt);
736 out.write("// Geozone points\n");
737 JavaScriptTools.writeJSVar(out, "jsvZoneCount" , pointCount);
738 JavaScriptTools.writeJSVar(out, "jsvZoneIndex" , DEFAULT_POINT_INDEX);
739 out.write("var jsvZoneList = new Array(\n"); // consistent with JSMapPoint
740 for (int z = 0; z < pointCount; z++) {
741 GeoPoint gp = (_selZone != null)? _selZone.getGeoPointAt(z,null) : null;
742 if (gp == null) { gp = GeoPoint.INVALID_GEOPOINT; }
743 out.write(" { lat:" + gp.getLatitude() + ", lon:" + gp.getLongitude() + " }");
744 if ((z+1) < pointCount) { out.write(","); }
745 out.write("\n");
746 }
747 out.write(" );\n");
748
749 /* end JavaScript */
750 JavaScriptTools.writeEndJavaScript(out);
751
752 /* Geozone.js */
753 JavaScriptTools.writeJSInclude(out, JavaScriptTools.qualifyJSFileRef("Geozone.js"), request);
754
755 }
756 }
757 };
758
759 /* Content */
760 final boolean mapControlsOnLeft =
761 ListTools.containsIgnoreCase(CONTROLS_ON_LEFT,privLabel.getStringProperty(PrivateLabel.PROP_ZoneInfo_mapControlLocation,""));
762 HTMLOutput HTML_CONTENT = new HTMLOutput(CommonServlet.CSS_CONTENT_FRAME, m) {
763 public void write(PrintWriter out) throws IOException {
764 String pageName = ZoneInfo.this.getPageName();
765
766 // -- frame header
767 //String menuURL = EncodeMakeURL(reqState,RequestProperties.TRACK_BASE_URI(),PAGE_MENU_TOP);
768 String menuURL = privLabel.getWebPageURL(reqState, PAGE_MENU_TOP);
769 String editURL = ZoneInfo.this.encodePageURL(reqState);//,RequestProperties.TRACK_BASE_URI());
770 String selectURL = ZoneInfo.this.encodePageURL(reqState);//,RequestProperties.TRACK_BASE_URI());
771 String newURL = ZoneInfo.this.encodePageURL(reqState);//,RequestProperties.TRACK_BASE_URI());
772
773 // -- Geozone GlobalActive
774 boolean globalActive = Geozone.IsGlobalActive();
775
776 if (_listZones) {
777
778 // -- Geozone selection table (Select, Geozone ID, Zone Name)
779 String frameTitle = _allowEdit?
780 i18n.getString("ZoneInfo.list.viewEditZone","View/Edit Geozone Information") :
781 i18n.getString("ZoneInfo.list.viewZone","View Geozone Information");
782 out.write("<span class='"+CommonServlet.CSS_MENU_TITLE+"'>"+frameTitle+"</span><br/>\n");
783 out.write("<hr>\n");
784
785 // -- Geozone selection table (Select, Zone ID, Zone Name)
786 out.write("<span class='"+CommonServlet.CSS_ADMIN_SELECT_TITLE+"'>"+FilterText(i18n.getString("ZoneInfo.list.selectZone","Select a Geozone"))+":</span>\n");
787 out.write("<div style='margin-left:25px;'>\n");
788 out.write("<form name='"+FORM_ZONE_SELECT+"' method='post' action='"+selectURL+"' target='_self'>"); // target='_top'
789 out.write("<input type='hidden' name='"+PARM_COMMAND+"' value='"+COMMAND_INFO_SELECT+"'/>");
790 out.write("<table class='"+CommonServlet.CSS_ADMIN_SELECT_TABLE+"' id='filter-table' cellspacing=0 cellpadding=0 border=0>\n");
791 out.write(" <thead>\n");
792 out.write(" <tr class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_ROW+"'>\n");
793 out.write(" <th class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_COL_SEL+"'>"+FilterText(i18n.getString("ZoneInfo.list.select","Select"))+"</th>\n");
794 out.write(" <th class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_COL +"'>"+FilterText(i18n.getString("ZoneInfo.list.zoneID","Geozone ID"))+"</th>\n");
795 out.write(" <th class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_COL +"'>"+FilterText(i18n.getString("ZoneInfo.list.description","Description\n(Address)"))+"</th>\n");
796 if (!globalActive) {
797 out.write(" <th class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_COL +"'>"+FilterText(i18n.getString("ZoneInfo.list.active","Active"))+"</th>\n");
798 }
799 if (showOverlapPriority) {
800 out.write(" <th class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_COL +"'>"+FilterText(i18n.getString("ZoneInfo.list.overlapPriority","Overlap\nPriority"))+"</th>\n");
801 }
802 out.write(" <th class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_COL +"'>"+FilterText(i18n.getString("ZoneInfo.list.zoneType","Zone\nType"))+"</th>\n");
803 if (showRevGeocodeZone) {
804 out.write(" <th class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_COL +"'>"+FilterText(i18n.getString("ZoneInfo.list.revGeocode","Reverse\nGeocode"))+"</th>\n");
805 }
806 if (showArriveDepartZone) {
807 out.write(" <th class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_COL +"'>"+FilterText(i18n.getString("ZoneInfo.list.arriveZone","Arrival\nZone"))+"</th>\n");
808 out.write(" <th class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_COL +"'>"+FilterText(i18n.getString("ZoneInfo.list.departZone","Departure\nZone"))+"</th>\n");
809 }
810 if (showClientUploadZone == 1) {
811 out.write(" <th class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_COL +"'>"+FilterText(i18n.getString("ZoneInfo.list.clientUpload","Device\nUpload"))+"</th>\n");
812 } else
813 if (showClientUploadZone == 2) {
814 out.write(" <th class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_COL +"'>"+FilterText(i18n.getString("ZoneInfo.list.clientUploadID","Device\nUpload ID"))+"</th>\n");
815 }
816 out.write(" <th class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_COL +"'>"+FilterText(i18n.getString("ZoneInfo.list.radiusMeters","Radius\n(meters)"))+"</th>\n");
817 out.write(" <th class='"+CommonServlet.CSS_ADMIN_TABLE_HEADER_COL +"'>"+FilterText(i18n.getString("ZoneInfo.list.centerPoint","Center\nLatitude/Longitude"))+"</th>\n");
818 out.write(" </tr>\n");
819 out.write(" </thead>\n");
820
821 /* geozone list */
822 out.write(" <tbody>\n");
823 int pointRadiusType = Geozone.GeozoneType.POINT_RADIUS.getIntValue();
824 int polygonType = Geozone.GeozoneType.POLYGON.getIntValue();
825 int corridorType = Geozone.GeozoneType.SWEPT_POINT_RADIUS.getIntValue();
826 for (int z = 0, r = 0; z < _zoneList.length; z++) {
827
828 /* get Geozone */
829 Geozone zone = null;
830 try {
831 zone = Geozone.getGeozone(currAcct, _zoneList[z], DEFAULT_SORT_ID, false);
832 } catch (DBException dbe) {
833 // error
834 }
835 if (zone == null) {
836 continue; // skip
837 }
838
839 /* geozone vars */
840 int zoneTypeInt = zone.getZoneType();
841 boolean zoneIsPOI = Geozone.isPointOfInterest(zone);
842 String zoneID = FilterText(zone.getGeozoneID());
843 String zoneDesc = FilterText(zone.getDescription());
844 String zoneActive = FilterText(ComboOption.getYesNoText(locale,zone.getIsActive()));
845 String zoneTypeStr = FilterText(zone.getZoneTypeDescription(locale));
846 String zoneRevGeo = FilterText(!zoneIsPOI?ComboOption.getYesNoText(locale,zone.getReverseGeocode()):"--");
847 String zoneRadius = zone.hasRadius()? String.valueOf(zone.getRadius()) : "--";
848 GeoPoint centerPt = zone.getGeoPointAt(DEFAULT_POINT_INDEX,null); // may be null if invalid
849 if (centerPt == null) { centerPt = new GeoPoint(0.0, 0.0); }
850 String zoneCenter = centerPt.getLatitudeString(GeoPoint.SFORMAT_DEC_5,null) + " "+GeoPoint.PointSeparator+" " + centerPt.getLongitudeString(GeoPoint.SFORMAT_DEC_5,null);
851 String checked = _selZoneID.equals(zone.getGeozoneID())? "checked" : "";
852 String styleClass = ((r++ & 1) == 0)? CommonServlet.CSS_ADMIN_TABLE_BODY_ROW_ODD : CommonServlet.CSS_ADMIN_TABLE_BODY_ROW_EVEN;
853
854 int pointCount = ZoneInfo.getGeozoneSupportedPointCount(reqState, zoneTypeInt);
855 String typeColor = (pointCount > 0)? "black" : "red";
856
857 out.write(" <tr class='" + styleClass + "'>\n");
858 out.write(" <td class='"+CommonServlet.CSS_ADMIN_TABLE_BODY_COL_SEL+"' "+SORTTABLE_SORTKEY+"='"+z+"'>");
859 if (pointCount <= 0) {
860 out.write(" "); // not supported
861 } else
862 if ((zoneTypeInt == pointRadiusType) || (zoneTypeInt == polygonType) || (zoneTypeInt == corridorType)) {
863 out.write("<input type='radio' name='"+PARM_ZONE_SELECT+"' id='"+zoneID+"' value='"+zoneID+"' "+checked+">");
864 } else {
865 out.write(" "); // unrecognized type
866 }
867 out.write( "</td>\n");
868 out.write(" <td class='"+CommonServlet.CSS_ADMIN_TABLE_BODY_COL +"' nowrap><label for='"+zoneID+"'>"+zoneID+"</label></td>\n");
869 out.write(" <td class='"+CommonServlet.CSS_ADMIN_TABLE_BODY_COL +"' nowrap>"+zoneDesc+"</td>\n");
870 if (!globalActive) {
871 out.write(" <td class='"+CommonServlet.CSS_ADMIN_TABLE_BODY_COL +"' nowrap>"+zoneActive+"</td>\n");
872 }
873 if (showOverlapPriority) {
874 String zonePriority = FilterText(!zoneIsPOI?String.valueOf(zone.getPriority()):"--");
875 out.write(" <td class='"+CommonServlet.CSS_ADMIN_TABLE_BODY_COL +"' nowrap>"+zonePriority+"</td>\n");
876 }
877 out.write(" <td class='"+CommonServlet.CSS_ADMIN_TABLE_BODY_COL +"' nowrap style='color:"+typeColor+"'>"+zoneTypeStr+"</td>\n");
878 if (showRevGeocodeZone) {
879 out.write(" <td class='"+CommonServlet.CSS_ADMIN_TABLE_BODY_COL +"' nowrap>"+zoneRevGeo+"</td>\n");
880 }
881 if (showArriveDepartZone) {
882 String zoneArrNtfy = FilterText(!zoneIsPOI?ComboOption.getYesNoText(locale,zone.getArrivalZone()):"--");
883 String zoneDepNtfy = FilterText(!zoneIsPOI?ComboOption.getYesNoText(locale,zone.getDepartureZone()):"--");
884 out.write(" <td class='"+CommonServlet.CSS_ADMIN_TABLE_BODY_COL +"' nowrap>"+zoneArrNtfy+"</td>\n");
885 out.write(" <td class='"+CommonServlet.CSS_ADMIN_TABLE_BODY_COL +"' nowrap>"+zoneDepNtfy+"</td>\n");
886 }
887 if (showClientUploadZone == 1) {
888 String zoneUpload = FilterText(!zoneIsPOI?ComboOption.getYesNoText(locale,zone.getClientUpload()||(zone.getClientID() > 0)):"--");
889 out.write(" <td class='"+CommonServlet.CSS_ADMIN_TABLE_BODY_COL +"' nowrap>"+zoneUpload+"</td>\n");
890 } else
891 if (showClientUploadZone == 2) {
892 String zoneUpldID = (zone.getClientID() > 0)? String.valueOf(zone.getClientID()) : "--";
893 out.write(" <td class='"+CommonServlet.CSS_ADMIN_TABLE_BODY_COL +"' nowrap>"+zoneUpldID+"</td>\n");
894 }
895 out.write(" <td class='"+CommonServlet.CSS_ADMIN_TABLE_BODY_COL +"' nowrap>"+zoneRadius+"</td>\n");
896 out.write(" <td class='"+CommonServlet.CSS_ADMIN_TABLE_BODY_COL +"' nowrap>"+zoneCenter+"</td>\n");
897 out.write(" </tr>\n");
898
899 }
900 out.write(" </tbody>\n");
901 out.write("</table>\n");
902 out.write("<table cellpadding='0' cellspacing='0' border='0' style='width:95%; margin-top:5px; margin-left:5px; margin-bottom:5px;'>\n");
903 out.write("<tr>\n");
904 if (_allowView ) {
905 out.write("<td style='padding-left:5px;'>");
906 out.write("<input type='submit' name='"+PARM_SUBMIT_VIEW+"' value='"+i18n.getString("ZoneInfo.list.view","View")+"'>");
907 out.write("</td>\n");
908 }
909 if (_allowEdit ) {
910 out.write("<td style='padding-left:5px;'>");
911 out.write("<input type='submit' name='"+PARM_SUBMIT_EDIT+"' value='"+i18n.getString("ZoneInfo.list.edit","Edit")+"'>");
912 out.write("</td>\n");
913 }
914 out.write("<td style='width:100%; text-align:right; padding-right:10px;'>");
915 if (_allowDelete) {
916 out.write("<input type='submit' name='"+PARM_SUBMIT_DEL+"' value='"+i18n.getString("ZoneInfo.list.delete","Delete")+"' "+Onclick_ConfirmDelete(locale)+">");
917 } else {
918 out.write(" ");
919 }
920 out.write("</td>\n");
921 out.write("</tr>\n");
922 out.write("</table>\n");
923
924 out.write("</form>\n");
925 out.write("</div>\n");
926 out.write("<hr>\n");
927
928 /* new Geozone */
929 if (_allowNew) {
930 out.write("<h1 class='"+CommonServlet.CSS_ADMIN_SELECT_TITLE+"'>"+FilterText(i18n.getString("ZoneInfo.list.createNewZone","Create a new Geozone"))+":</h1>\n");
931 out.write("<div style='margin-top:5px; margin-left:5px; margin-bottom:5px;'>\n");
932 out.write("<form name='"+FORM_ZONE_NEW+"' method='post' action='"+newURL+"' target='_self'>"); // target='_top'
933 out.write(" <input type='hidden' name='"+PARM_COMMAND+"' value='"+COMMAND_INFO_NEW+"'/>");
934 out.write(FilterText(i18n.getString("ZoneInfo.list.zoneID","Geozone ID"))+": <input type='text' class='"+CommonServlet.CSS_TEXT_INPUT+"' name='"+PARM_NEW_ID+"' value='' size='32' maxlength='32'>");
935 int polyPointCount = ZoneInfo.getGeozoneSupportedPointCount(reqState,polygonType );
936 int corrPointCount = ZoneInfo.getGeozoneSupportedPointCount(reqState,corridorType);
937 if ((polyPointCount > 0) || (corrPointCount > 0)) {
938 ComboMap zoneTypeList = new ComboMap();
939 out.write(" ");
940 zoneTypeList.add(String.valueOf(pointRadiusType) , Geozone.GeozoneType.POINT_RADIUS.toString(locale));
941 if (polyPointCount > 0) {
942 zoneTypeList.add(String.valueOf(polygonType) , Geozone.GeozoneType.POLYGON.toString(locale));
943 }
944 if (corrPointCount > 0) {
945 zoneTypeList.add(String.valueOf(corridorType), Geozone.GeozoneType.SWEPT_POINT_RADIUS.toString(locale));
946 }
947 out.print(Form_ComboBox(PARM_NEW_TYPE,PARM_NEW_TYPE,true,zoneTypeList,"","", -1));
948 } else {
949 // only POINT_RADIUS supported
950 }
951 out.write("<br>\n");
952 out.write(" <input type='submit' name='"+PARM_SUBMIT_NEW+"' value='"+i18n.getString("ZoneInfo.list.new","New")+"' style='margin-top:5px; margin-left:10px;'>\n");
953 out.write("</form>\n");
954 out.write("</div>\n");
955 out.write("<hr>\n");
956 }
957
958 } else {
959
960 // -- view/edit
961 int selZoneType = (_selZone != null)? _selZone.getZoneType() : Geozone.GeozoneType.POINT_RADIUS.getIntValue();
962 boolean selZoneIsPOI = Geozone.isPointOfInterest(_selZone); // false if _selZone is null
963
964 // -- begin form
965 out.println("<form name='"+FORM_ZONE_EDIT+"' method='post' action='"+editURL+"' target='_self'>"); // target='_top'
966
967 // -- Geozone view/edit form
968 out.write("<table cellspacing='0' cellpadding='0' border='0'><tr>\n");
969 out.write("<td nowrap>");
970 String frameTitle = _editZone?
971 i18n.getString("ZoneInfo.map.editZone","Edit Geozone") :
972 i18n.getString("ZoneInfo.map.viewZone","View Geozone");
973 out.print ("<span style='font-size:9pt; font-weight:bold;'>"+frameTitle+" </span>");
974 out.print (Form_TextField(PARM_ZONE_SELECT, false, _selZoneID, 16, 20));
975 out.write("</td>");
976 out.write("<td nowrap style=\"width:100%; text-align:right;\">");
977 //out.println("<span style='width:100%;'> </span>"); <-- causes IE to NOT display the following description
978 String i18nAddressTooltip = i18n.getString("ZoneInfo.map.description.tooltip", "This description is used for custom reverse-geocoding");
979 out.print ("<span class='zoneDescription' style='width:100%;' title=\""+i18nAddressTooltip+"\">");
980 out.print ("<b>"+i18n.getString("ZoneInfo.map.description","Description (Address)")+"</b>: ");
981 out.print (Form_TextField(PARM_ZONE_DESC, _editZone, (_selZone!=null)?_selZone.getDescription():"", 30, 64));
982 out.println("</span>");
983 out.write("</td>");
984 out.write("</tr></table>");
985
986 //out.println("<br/>");
987 out.println("<input type='hidden' name='"+PARM_COMMAND+"' value='"+COMMAND_INFO_UPDATE+"'/>");
988
989 out.println("<table border='0' cellpadding='0' cellspacing='0' style='padding-top:3px'>"); // {
990 out.println("<tr>");
991
992 /* map (controls on right) */
993 MapDimension mapDim = (mapProvider != null)? mapProvider.getZoneDimension() : new MapDimension(-1,-1);
994 if (!mapControlsOnLeft) {
995 String mapWidth = (mapDim.getWidth() <= 0)? "100%" : String.valueOf(mapDim.getWidth()) +"px";
996 String mapHeight = (mapDim.getHeight() <= 0)? "100%" : String.valueOf(mapDim.getHeight())+"px";
997 if (mapSupportsGeozones) {
998 out.println("<!-- Begin Map -->");
999 out.println("<td style='width:"+mapWidth+"; height:"+mapHeight+"; padding-right:5px;'>");
1000 mapProvider.writeMapCell(out, reqState, mapDim);
1001 out.println("</td>");
1002 out.println("<!-- End Map -->");
1003 } else {
1004 out.println("<td style='width:"+mapWidth+"; height:"+mapHeight+"; padding-right:5px; border: 1px solid black;'>");
1005 out.println("<!-- Geozones not yet supported for this MapProvider -->");
1006 out.println("<center>");
1007 out.println("<span style='font-size:12pt;'>");
1008 out.println(i18n.getString("ZoneInfo.map.notSupported","Geozone map not yet supported for this MapProvider"));
1009 out.println(" </span>");
1010 out.println("</center>");
1011 out.println("</td>");
1012 }
1013 }
1014
1015 /* Geozone fields */
1016 out.println("<td valign='top' style='width:230px; min-width:230px; border-top: solid #CCCCCC 1px;'>");
1017
1018 // -- active
1019 if (!Geozone.IsGlobalActive()) {
1020 String i18nActiveTooltip = i18n.getString("ZoneInfo.map.active.tooltip", "Select to enable/activate this Geozone");
1021 out.println("<div class='zoneCheckSelect' title=\""+i18nActiveTooltip+"\">");
1022 out.println(Form_CheckBox(PARM_ZONE_ACTIVE, PARM_ZONE_ACTIVE, _editZone, ((_selZone!=null) && _selZone.getIsActive()),null,null));
1023 out.println("<b><label for='"+PARM_ZONE_ACTIVE+"'>"+i18n.getString("ZoneInfo.map.active","Active")+"</label></b>");
1024 out.println("</div>");
1025 }
1026
1027 // -- overlap priority
1028 if (showOverlapPriority && !selZoneIsPOI) {
1029 String i18nPriorityTooltip = i18n.getString("ZoneInfo.map.overlapPriority.tooltip", "Priority used when multiple Geozones overlap");
1030 out.println("<div class='zonePrioritySelect' title=\""+i18nPriorityTooltip+"\">");
1031 int pri = (_selZone != null)? _selZone.getPriority() : 0;
1032 if (pri < 0) {
1033 pri = 0;
1034 } else
1035 if (pri >= OVERLAP_PRIORITY.length) {
1036 pri = OVERLAP_PRIORITY.length - 1;
1037 }
1038 ComboMap priCombo = new ComboMap(OVERLAP_PRIORITY);
1039 String priSel = OVERLAP_PRIORITY[pri];
1040 out.println("<b><label for='"+PARM_PRIORITY+"'>"+i18n.getString("ZoneInfo.map.overlapPriority","Overlap Priority")+": </label></b>");
1041 out.println(Form_ComboBox(PARM_PRIORITY, PARM_PRIORITY, _editZone, priCombo, priSel, null, 6));
1042 out.println("</div>");
1043 }
1044
1045 // -- show assigned device group
1046 if (showAssignedDevGroup && !selZoneIsPOI) {
1047 String acctID = currAcct.getAccountID();
1048 String userID = (currUser != null)? currUser.getUserID() : User.getAdminUserID();
1049 java.util.List<String> devGrps = null;
1050 boolean limitToGroups = privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_limitToUserDeviceGroups,false);
1051 if (limitToGroups && !User.isAdminUser(userID)) {
1052 // -- specific user authorized groups
1053 try {
1054 java.util.List<String> grps = User.getExplicitlyAuthorizedDeviceGroupIDs(DBReadWriteMode.READ_WRITE,acctID,userID,-1L);
1055 if (!ListTools.isEmpty(grps)) {
1056 devGrps = new Vector<String>(grps);
1057 }
1058 } catch (DBException dbe) {
1059 devGrps = null;
1060 }
1061 } else {
1062 // -- admin user
1063 try {
1064 boolean includeAll = true;
1065 java.util.List<String> grps = DeviceGroup.getDeviceGroupsForAccount(DBReadWriteMode.READ_WRITE,acctID,includeAll);
1066 if (!ListTools.isEmpty(grps)) {
1067 devGrps = grps;
1068 }
1069 } catch (DBException dbe) {
1070 devGrps = null;
1071 }
1072 }
1073 if (!ListTools.isEmpty(devGrps)) {
1074 String i18nGroupTooltip = i18n.getString("ZoneInfo.map.deviceGroups.tooltip", "Select to Assign Group to Geozone");
1075 //for (String dg : devGrps) { Print.logInfo(" Device Group: " + dg); }
1076 ComboMap grpMap = new ComboMap(devGrps);
1077 String selGrp = (_selZone!=null)? _selZone.getGroupID() : null;
1078 if (StringTools.isBlank(selGrp)) {
1079 selGrp = DeviceGroup.DEVICE_GROUP_ALL;
1080 }
1081 out.println("<div class='zoneGroupSelect' title=\""+i18nGroupTooltip+"\">");
1082 out.println("<label for='"+PARM_GROUP_SELECT+"'><b>"+i18n.getString("ZoneInfo.assignGroup","Assign Group")+"</b></label>");
1083 out.println(Form_ComboBox(PARM_GROUP_SELECT, PARM_GROUP_SELECT, _editZone, grpMap, selGrp, null/*onchange*/));
1084 out.println("</div>");
1085 }
1086 }
1087
1088 // -- reverse-geocode zone
1089 if (showRevGeocodeZone && !selZoneIsPOI) {
1090 String i18nRevGeoTooltip = i18n.getString("ZoneInfo.map.reverseGeocode.tooltip", "Select to use this zone for custom reverse-geocoding");
1091 out.println("<div class='zoneCheckSelect' title=\""+i18nRevGeoTooltip+"\">");
1092 out.println(Form_CheckBox(PARM_REV_GEOCODE, PARM_REV_GEOCODE, _editZone, ((_selZone!=null) && _selZone.getReverseGeocode()),null,null));
1093 out.println("<b><label for='"+PARM_REV_GEOCODE+"'>"+i18n.getString("ZoneInfo.map.reverseGeocode","Reverse Geocode")+"</label></b>");
1094 out.println("</div>");
1095 }
1096
1097 // -- arrival zone
1098 if (showArriveDepartZone && !selZoneIsPOI) {
1099 String i18nArriveTooltip = i18n.getString("ZoneInfo.map.arrivalZone.tooltip", "Select to use this zone for 'Arrival' checking");
1100 boolean checked = ((_selZone!=null) && _selZone.getArrivalZone())? true : false;
1101 out.println("<div class='zoneCheckSelect' title=\""+i18nArriveTooltip+"\">");
1102 if (showArriveDepartCode) {
1103 int sc = (_selZone != null)? _selZone.getArrivalStatusCode() : StatusCodes.STATUS_GEOFENCE_ARRIVE;
1104 String sck = "0x" + StringTools.toHexString(sc,16);
1105 ComboMap scm = ZoneInfo.getArrivalCodeComboMap(privLabel);
1106 String chg = _editZone? "javascript:document."+FORM_ZONE_EDIT+"."+PARM_ARRIVE_CODE+".disabled=!document."+FORM_ZONE_EDIT+"."+PARM_ARRIVE_NOTIFY+".checked;" : null;
1107 out.println(Form_CheckBox(PARM_ARRIVE_NOTIFY, PARM_ARRIVE_NOTIFY, _editZone, checked,null,chg));
1108 out.println("<b><label for='"+PARM_ARRIVE_NOTIFY+"'>"+i18n.getString("ZoneInfo.map.arrival","Arrive")+"</label></b> ");
1109 out.println(Form_ComboBox(PARM_ARRIVE_CODE, PARM_ARRIVE_CODE, _editZone && checked, scm, sck, null, 14));
1110 } else {
1111 out.println(Form_CheckBox(PARM_ARRIVE_NOTIFY, PARM_ARRIVE_NOTIFY, _editZone, checked,null,null));
1112 out.println("<b><label for='"+PARM_ARRIVE_NOTIFY+"'>"+i18n.getString("ZoneInfo.map.arrivalZone","Arrival Zone")+"</label></b>");
1113 }
1114 out.println("</div>");
1115 }
1116
1117 // -- departure zone
1118 if (showArriveDepartZone && !selZoneIsPOI) {
1119 String i18nDepartTooltip = i18n.getString("ZoneInfo.map.departureZone.tooltip", "Select to use this zone for 'Departure' checking");
1120 boolean checked = ((_selZone!=null) && _selZone.getDepartureZone())? true : false;
1121 out.println("<div class='zoneCheckSelect' title=\""+i18nDepartTooltip+"\">");
1122 if (showArriveDepartCode) {
1123 int sc = (_selZone != null)? _selZone.getDepartureStatusCode() : StatusCodes.STATUS_GEOFENCE_DEPART;
1124 String sck = "0x" + StringTools.toHexString(sc,16);
1125 ComboMap scm = ZoneInfo.getDepartureCodeComboMap(privLabel);
1126 String chg = _editZone? "javascript:document."+FORM_ZONE_EDIT+"."+PARM_DEPART_CODE+".disabled=!document."+FORM_ZONE_EDIT+"."+PARM_DEPART_NOTIFY+".checked;" : null;
1127 out.println(Form_CheckBox(PARM_DEPART_NOTIFY, PARM_DEPART_NOTIFY, _editZone, checked,null,chg));
1128 out.println("<b><label for='"+PARM_DEPART_NOTIFY+"'>"+i18n.getString("ZoneInfo.map.departure","Depart")+"</label></b> ");
1129 out.println(Form_ComboBox(PARM_DEPART_CODE, PARM_DEPART_CODE, _editZone && checked, scm, sck, null, 14));
1130 } else {
1131 out.println(Form_CheckBox(PARM_DEPART_NOTIFY, PARM_DEPART_NOTIFY, _editZone, checked,null,null));
1132 out.println("<b><label for='"+PARM_DEPART_NOTIFY+"'>"+i18n.getString("ZoneInfo.map.departureZone","Departure Zone")+"</label></b>");
1133 }
1134 out.println("</div>");
1135 }
1136
1137 // -- auto notify
1138 if (showArriveDepartZone && showAutoNotify && !selZoneIsPOI) {
1139 String i18nAutoTooltip = i18n.getString("ZoneInfo.map.autoNotify.tooltip", "Select to automatically send notification on arrive/depart");
1140 out.println("<div class='zoneCheckSelect' title=\""+i18nAutoTooltip+"\">");
1141 out.println(Form_CheckBox(PARM_AUTO_NOTIFY, PARM_AUTO_NOTIFY, _editZone, ((_selZone!=null) && _selZone.getAutoNotify()),null,null));
1142 out.println("<b><label for='"+PARM_AUTO_NOTIFY+"'>"+i18n.getString("ZoneInfo.map.autoNotify","Auto Notify")+"</label></b>");
1143 out.println("</div>");
1144 }
1145
1146 // -- Client Upload ID
1147 if ((showClientUploadZone != 0) && !selZoneIsPOI) {
1148 String i18nUploadTooltip = i18n.getString("ZoneInfo.map.clientUpload.tooltip", "Select to use for client-side geofence");
1149 out.println("<div class='zoneCheckSelect' title=\""+i18nUploadTooltip+"\">");
1150 if (showClientUploadZone == 1) {
1151 out.println(Form_CheckBox(PARM_CLIENT_UPLOAD, PARM_CLIENT_UPLOAD, _editZone, ((_selZone!=null) && _selZone.getClientUpload()),null,null));
1152 out.println("<b><label for='"+PARM_CLIENT_UPLOAD+"'>"+i18n.getString("ZoneInfo.map.clientUpload","Device Upload")+":</label></b> ");
1153 } else
1154 if (showClientUploadZone == 2) {
1155 out.println("<b>"+i18n.getString("ZoneInfo.map.clientUploadID","Device Upload ID")+":</b> ");
1156 out.println(Form_TextField(PARM_CLIENT_ID, PARM_CLIENT_ID, _editZone, (_selZone!=null)?String.valueOf(_selZone.getClientID()):"", 5, 5));
1157 }
1158 out.println("</div>");
1159 }
1160
1161 // -- geozone points section
1162 out.println("<hr>");
1163
1164 /* notes */
1165 if (_editZone && mapSupportsGeozones) {
1166 out.println("<div class='zoneNotesBasic'>");
1167 //out.println("<i>"+i18nx.getString("ZoneInfo.map.notes.basic", "The Geozone loc/size may be changed here, click 'RESET' to update.")+"</i>");
1168 out.println("<i>"+i18n.getString("ZoneInfo.map.notes.basic", "Geozone attributes:")+"</i>");
1169 out.println("</div>");
1170 }
1171
1172 /* shape color */
1173 if (privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_showShapeColor,false) && !selZoneIsPOI) {
1174 ComboMap colorCombo = GetColorComboMap(i18n);
1175 String color = (_selZone != null)? _selZone.getShapeColor() : "";
1176 String onchange = _editZone? "javascript:jsvZoneColor=document."+FORM_ZONE_EDIT+"."+PARM_ZONE_COLOR+".value;_zoneReset();" : null;
1177 out.println("<div class='zoneColorSelect' title=\""+""+"\">");
1178 out.println("<b><label for='"+PARM_ZONE_COLOR+"'>"+i18n.getString("ZoneInfo.map.shapeColor","Zone Color")+": </label></b>");
1179 out.println(Form_ComboBox(PARM_ZONE_COLOR, PARM_ZONE_COLOR, _editZone, colorCombo, color, onchange, 10));
1180 out.println("</div>");
1181 }
1182
1183 /* pushpin (show description pushpin on maps) */
1184 if (privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_showPushpins,false) || selZoneIsPOI) {
1185 // -- TODO: this should also show the pushpin image
1186 ComboMap ppCombo = GetPushpinComboMap(i18n, reqState);
1187 String ppID = (_selZone != null)? _selZone.getIconName() : "";
1188 out.println("<div class='zonePushpinSelect' title=\""+""+"\">");
1189 out.println("<b><label for='"+PARM_ZONE_PUSHPIN+"'>"+i18n.getString("ZoneInfo.map.pushpin","Pushpin")+": </label></b>");
1190 out.println(Form_ComboBox(PARM_ZONE_PUSHPIN, PARM_ZONE_PUSHPIN, _editZone, ppCombo, ppID, null/*onchange*/, 12));
1191 out.println("</div>");
1192 }
1193
1194 /* radius */
1195 Geozone.GeozoneType gzt = Geozone.getGeozoneType(_selZone);
1196 if (gzt.hasRadius()) {
1197 double minRad = Geozone.GetMinimumRadius(gzt.getIntValue());
1198 double maxRad = Geozone.GetMaximumRadius(gzt.getIntValue());
1199 String i18nRadiusTooltip = i18n.getString("ZoneInfo.map.radius.tooltip", "Radius may be between {0} and {1} meters",
1200 String.valueOf((long)minRad), String.valueOf((long)maxRad));
1201 out.println("<div class='zoneRadius' title=\""+i18nRadiusTooltip+"\">");
1202 out.print ("<b>"+i18n.getString("ZoneInfo.map.radiusMeters","Radius (meters)")+":</b> ");
1203 out.println(Form_TextField(MapProvider.ID_ZONE_RADIUS_M, PARM_ZONE_RADIUS, _editZone, (_selZone!=null)?String.valueOf(_selZone.getRadius()):"", 7, 7));
1204 out.println("</div>");
1205 } else {
1206 out.println("<input type='hidden' id='"+MapProvider.ID_ZONE_RADIUS_M+"' name='"+PARM_ZONE_RADIUS+"' value='0'/>");
1207 }
1208
1209 out.println("<div class='zoneLatLon'>");
1210 out.println("<b>"+i18n.getString("ZoneInfo.map.latLon","Lat/Lon")+"</b>: ");
1211 if (_editZone && mapSupportsGeozones) {
1212 String i18nResetBtn = i18n.getString("ZoneInfo.map.reset","Reset Map");
1213 String i18nResetTooltip = i18n.getString("ZoneInfo.map.reset.tooltip", "Click to update the map with the specified radius/latitude/longitude");
1214 out.print("<input class='formButton' type='button' name='reset' value='"+i18nResetBtn+"' title=\""+i18nResetTooltip+"\" onclick=\"javascript:_zoneReset();\">");
1215 }
1216 out.println("<br>");
1217 out.println("<div style='height:200px; overflow-y:auto;'>"); // beginning of vertice list
1218 int pointCount = ZoneInfo.getGeozoneSupportedPointCount(reqState, selZoneType);
1219 for (int z = 0; z < pointCount; z++) {
1220 GeoPoint gp = _selZone.getGeoPointAt(z,null);
1221 double gpLat = (gp != null)? gp.getLatitude() : 0.0;
1222 double gpLon = (gp != null)? gp.getLongitude() : 0.0;
1223 String latStr = (_selZone != null)? String.valueOf(gpLat) : "";
1224 String lonStr = (_selZone != null)? String.valueOf(gpLon) : "";
1225 // -- id='"+PARM_ZONE_INDEX+"'
1226 if (pointCount > 1) {
1227 String chk = (z == 0)? " checked" : "";
1228 out.println("<input type='radio' name='"+PARM_ZONE_INDEX+"' value='" + z + "' "+chk+" onclick=\"javascript:_zonePointSelectionChanged("+z+")\"/> ");
1229 // onchange=
1230 } else {
1231 out.println("<input type='hidden' name='"+PARM_ZONE_INDEX+"' value='" + z + "'/>");
1232 }
1233 String latCSS = _editZone? "zoneLatLonText" : "zoneLatLonText_ro";
1234 String lonCSS = _editZone? "zoneLatLonText" : "zoneLatLonText_ro";
1235 out.println(Form_TextField(MapProviderAdapter.ID_ZONE_LATITUDE (z), PARM_ZONE_LATITUDE (z), _editZone, latStr, null, 7, 9, latCSS));
1236 out.println(Form_TextField(MapProviderAdapter.ID_ZONE_LONGITUDE(z), PARM_ZONE_LONGITUDE(z), _editZone, lonStr, null, 8, 10, lonCSS));
1237 if ((z+1) < pointCount) { out.println("<br>"); }
1238 }
1239 out.println("</div>"); // end of vertice list
1240 // -- Speed limit
1241 if (mapSupportsGeozones && showSpeedLimit && !selZoneIsPOI) {
1242 Account.SpeedUnits speedUnit = Account.getSpeedUnits(currAcct); // not null
1243 double kphLimit = (_selZone != null)? _selZone.getSpeedLimitKPH() : 0.0;
1244 double speedLimit = speedUnit.convertFromKPH(kphLimit);
1245 out.print("<hr>\n");
1246 out.println("<div class='zoneSpeedLimit' title=\""+""+"\">");
1247 out.println("<b>"+i18n.getString("ZoneInfo.speedLimit","Speed Limit ({0})",speedUnit.toString(locale))+":</b>");
1248 out.println(Form_TextField(PARM_SPEED_LIMIT, PARM_SPEED_LIMIT, _editZone, String.valueOf(speedLimit), 5, 5));
1249 out.println("</div>");
1250 }
1251 // Purpose
1252 if (showPurposeIDs) {
1253 String purpID = (_selZone != null)? _selZone.getZonePurposeID() : "";
1254 String Pstr = privLabel.getStringProperty(PrivateLabel.PROP_ZoneInfo_zonePurposeList,null);
1255 String P[] = !StringTools.isBlank(Pstr)? StringTools.split(Pstr,',') : null;
1256 out.print("<hr>\n");
1257 out.println("<div class='zonePurposeID' title=\""+""+"\">");
1258 out.println("<b>"+i18n.getString("ZoneInfo.purposeID","Purpose")+":</b> ");
1259 if (!ListTools.isEmpty(P)) {
1260 ComboMap purpMap = new ComboMap(P);
1261 if (!ListTools.contains(P,purpID)) { purpMap.add(purpID); }
1262 out.println(Form_ComboBox(PARM_PURPOSE_ID, PARM_PURPOSE_ID, _editZone, purpMap, purpID, null/*onchange*/));
1263 } else {
1264 out.println(Form_TextField(PARM_PURPOSE_ID, PARM_PURPOSE_ID, _editZone, purpID, 16, 30));
1265 }
1266 out.println("</div>");
1267 }
1268 // GeoCorridor
1269 if (showCorridorIDs && !selZoneIsPOI) {
1270 String corrID = (_selZone != null)? _selZone.getCorridorID() : "";
1271 out.print("<hr>\n");
1272 out.println("<div class='zoneCorridorID' title=\""+""+"\">");
1273 out.println("<b>"+i18n.getString("ZoneInfo.corridorID","Corridor ID")+":</b>");
1274 out.println("<br>");
1275 out.println(Form_TextField(PARM_CORRIDOR_ID, PARM_CORRIDOR_ID, _editZone, corrID, 24, 30));
1276 out.println("</div>");
1277 }
1278 // "Center On Zip/Address"
1279 if (_editZone && mapSupportsGeozones) {
1280 // "ZipCode" button
1281 if (privLabel.getBooleanProperty(PrivateLabel.PROP_ZoneInfo_enableGeocode,false)) {
1282 GeocodeProvider gcp = privLabel.getGeocodeProvider();
1283 String dftCountryCode = privLabel.getStringProperty(PrivateLabel.PROP_ZoneInfo_enableGeocode_country,"US");
1284 String i18nZipBtn = "";
1285 if ((gcp == null) || gcp.getName().startsWith("geonames")) {
1286 i18nZipBtn = i18n.getString("ZoneInfo.map.geocodeZip","Center On City/ZipCode");
1287 } else {
1288 i18nZipBtn = i18n.getString("ZoneInfo.map.geocodeAddress","Center On Address", gcp.getName());
1289 }
1290 String i18nZipTooltip = i18n.getString("ZoneInfo.map.geocode.tooltip", "Click to reset Geozone to spcified Address/ZipCode");
1291 String rgZipCode_text = "rgZipCode";
1292 out.print("<hr>\n");
1293 //out.print("<br>");
1294 out.print("<input class='formButton' type='button' name='tozip' value='"+i18nZipBtn+"' title=\""+i18nZipTooltip+"\" onclick=\"javascript:_zoneGotoAddr(jsmGetIDValue('"+rgZipCode_text+"'),'"+dftCountryCode+"');\">");
1295 out.print("<br>");
1296 out.println(Form_TextField(rgZipCode_text, rgZipCode_text, _editZone, "", 27, 60));
1297 }
1298 }
1299 out.println("</div>");
1300
1301 out.println("<hr>");
1302 out.println("<div class='zoneInstructions'>");
1303 out.println("<b>"+i18n.getString("ZoneInfo.map.notes.header","Geozone Notes/Instructions")+":</b><br>");
1304 if (_editZone && mapSupportsGeozones) {
1305 String instr[] = mapProvider.getGeozoneInstructions(selZoneType, locale);
1306 if ((instr != null) && (instr.length > 0)) {
1307 for (int i = 0; i < instr.length; i++) {
1308 if (!StringTools.isBlank(instr[i])) {
1309 out.println("- " + FilterText(instr[i]) + "<br>");
1310 }
1311 }
1312 }
1313 }
1314 out.println("- " + i18n.getString("ZoneInfo.map.notes.lengthInMeters", "Distances are always in meters.") + "<br>");
1315
1316 out.println("<hr>");
1317 if (mapSupportsCursorLocation || mapSupportsDistanceRuler) {
1318 if (mapSupportsCursorLocation) {
1319 out.println("<b>"+i18n.getString("ZoneInfo.map.cursorLoc","Cursor")+"</b>:");
1320 out.println("<span id='"+MapProvider.ID_LAT_LON_DISPLAY +"' style='margin-left:6px; margin-bottom:3px;'>0.0000,0.0000</span>");
1321 }
1322 if (mapSupportsDistanceRuler) {
1323 if (mapSupportsCursorLocation) { out.println("<br>"); }
1324 out.println("<b>"+i18n.getString("ZoneInfo.map.distanceRuler","Distance")+"</b>:");
1325 out.println("<span id='"+MapProvider.ID_DISTANCE_DISPLAY+"' style='margin-left:6px;'>0 "+GeoPoint.DistanceUnits.METERS.toString(locale)+"</span>");
1326 }
1327 out.println("<hr>");
1328 }
1329
1330 out.println("</div>");
1331
1332 out.write("<div width='100%'>\n");
1333 out.write("<span style='padding-left:10px'> </span>\n");
1334 if (_editZone) {
1335 out.write("<input type='submit' name='"+PARM_SUBMIT_CHG+"' value='"+i18n.getString("ZoneInfo.map.change","Change")+"'>\n");
1336 out.write("<span style='padding-left:10px'> </span>\n");
1337 out.write("<input type='button' name='"+PARM_BUTTON_CANCEL+"' value='"+i18n.getString("ZoneInfo.map.cancel","Cancel")+"' onclick=\"javascript:openURL('"+editURL+"','_self');\">\n"); // target='_top'
1338 } else {
1339 out.write("<input type='button' name='"+PARM_BUTTON_BACK+"' value='"+i18n.getString("ZoneInfo.map.back","Back")+"' onclick=\"javascript:openURL('"+editURL+"','_self');\">\n"); // target='_top'
1340 }
1341 out.write("</div>\n");
1342
1343 out.println("<div width='100%' height='100%'>");
1344 out.println(" ");
1345 out.println("</div>");
1346
1347 out.println("</td>");
1348
1349 /* map (controls on left) */
1350 if (mapControlsOnLeft) {
1351 String mapWidth = (mapDim.getWidth() <= 0)? "100%" : String.valueOf(mapDim.getWidth()) +"px";
1352 String mapHeight = (mapDim.getHeight() <= 0)? "100%" : String.valueOf(mapDim.getHeight())+"px";
1353 if (mapSupportsGeozones) {
1354 out.println("<!-- Begin Map -->");
1355 out.println("<td style='width:"+mapWidth+"; height:"+mapHeight+"; padding-left:5px;'>");
1356 mapProvider.writeMapCell(out, reqState, mapDim);
1357 out.println("</td>");
1358 out.println("<!-- End Map -->");
1359 } else {
1360 out.println("<td style='width:"+mapWidth+"; height:"+mapHeight+"; padding-left:5px; border: 1px solid black;'>");
1361 out.println("<!-- Geozones not yet supported for this MapProvider -->");
1362 out.println("<center>");
1363 out.println("<span style='font-size:12pt;'>");
1364 out.println(i18n.getString("ZoneInfo.map.notSupported","Geozone map not yet supported for this MapProvider"));
1365 out.println(" </span>");
1366 out.println("</center>");
1367 out.println("</td>");
1368 }
1369 }
1370
1371 /* end of form */
1372 out.println("</tr>");
1373 out.println("</table>"); // }
1374 out.println("</form>");
1375
1376 }
1377
1378 }
1379 };
1380
1381 /* map load? */
1382 String mapOnLoad = _listZones? "" : "javascript:_zoneMapOnLoad();";
1383 String mapOnUnload = _listZones? "" : "javascript:_zoneMapOnUnload();";
1384
1385 /* write frame */
1386 String onload = error? (mapOnLoad + JS_alert(false,m)) : mapOnLoad;
1387 CommonServlet.writePageFrame(
1388 reqState,
1389 onload,mapOnUnload, // onLoad/onUnload
1390 HTML_CSS, // Style sheets
1391 HTML_JS, // Javascript
1392 null, // Navigation
1393 HTML_CONTENT); // Content
1394
1395 }
1396
1397 // ------------------------------------------------------------------------
1398}
1399
1400
1401