001/** 002 * Copyright 2014 Tampere University of Technology, Pori Department 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package service.tut.pori.contentanalysis; 017 018import java.util.HashMap; 019import java.util.Iterator; 020import java.util.List; 021import java.util.Map; 022import java.util.Map.Entry; 023 024import org.apache.commons.lang3.StringUtils; 025import org.apache.commons.lang3.tuple.Pair; 026import org.apache.log4j.Logger; 027import org.springframework.beans.factory.annotation.Autowired; 028import org.springframework.jdbc.core.JdbcTemplate; 029import org.springframework.jdbc.core.simple.SimpleJdbcInsert; 030import org.springframework.transaction.TransactionStatus; 031import org.springframework.transaction.support.TransactionCallback; 032 033import service.tut.pori.contentanalysis.AbstractTaskDetails.TaskParameters; 034import service.tut.pori.contentanalysis.AsyncTask.TaskStatus; 035import service.tut.pori.contentanalysis.AsyncTask.TaskType; 036import core.tut.pori.dao.SQLDAO; 037import core.tut.pori.dao.clause.SQLClause.SQLType; 038import core.tut.pori.http.parameters.DataGroups; 039import core.tut.pori.http.parameters.Limits; 040import core.tut.pori.users.UserIdentity; 041 042/** 043 * Base class for task DAOs 044 * 045 * Note that this class is <i>NOT</i> abstract, and it can be used to implement core task details ({@link service.tut.pori.contentanalysis.AbstractTaskDetails}), 046 * but the class is not guaranteed to function with extended capabilities provided by inherited classes. Use the service specific implementation when needed. 047 * 048 */ 049public class TaskDAO extends SQLDAO { 050 private static final Logger LOGGER = Logger.getLogger(TaskDAO.class); 051 private static final String METADATA_TASK_PARAMETER_CLASS = "METADATA_TP_CLS"; 052 /* tables */ 053 private static final String TABLE_TASKS = DATABASE +".ca_tasks"; 054 private static final String TABLE_TASK_BACKENDS = DATABASE +".ca_tasks_backends"; 055 private static final String TABLE_TASK_METADATA = DATABASE +".ca_tasks_metadata"; 056 /* columns */ 057 /** default column name for status messages */ 058 protected static final String COLUMN_MESSAGE = "message"; 059 /** default column name for task ids */ 060 protected static final String COLUMN_TASK_ID = "task_id"; 061 /** default column name for task type */ 062 protected static final String COLUMN_TASK_TYPE = "task_type"; 063 private static final String[] SQL_COLUMNS_INSERT_TASK = new String[]{COLUMN_TASK_TYPE, COLUMN_ROW_CREATED, COLUMN_USER_ID}; 064 065 /* sql strings */ 066 private static final String SQL_CHECK_TASK_BACKEND = "SELECT "+COLUMN_COUNT+" FROM "+TABLE_TASK_BACKENDS+" WHERE "+Definitions.COLUMN_BACKEND_ID+"=? AND "+COLUMN_TASK_ID+"=? LIMIT 1"; 067 private static final int[] SQL_CHECK_TASK_BACKEND_TYPES = new int[]{SQLType.INTEGER.toInt(), SQLType.LONG.toInt()}; 068 069 private static final String SQL_GET_BACKEND_STATUSES = "SELECT "+Definitions.COLUMN_BACKEND_ID+", "+Definitions.COLUMN_STATUS+", "+COLUMN_MESSAGE+" FROM "+TABLE_TASK_BACKENDS+" WHERE "+COLUMN_TASK_ID+"=?"; 070 private static final int[] SQL_GET_BACKEND_STATUSES_SQL_TYPES = new int[]{SQLType.LONG.toInt()}; 071 072 private static final String SQL_INSERT_TASK_BACKEND = "INSERT INTO "+TABLE_TASK_BACKENDS+" ("+COLUMN_TASK_ID+", "+Definitions.COLUMN_BACKEND_ID+", "+Definitions.COLUMN_STATUS+", "+COLUMN_MESSAGE+", "+COLUMN_ROW_CREATED+") VALUES (?,?,?,?,NOW())"; 073 private static final int[] SQL_INSERT_TASK_BACKEND_TYPES = new int[]{SQLType.LONG.toInt(), SQLType.INTEGER.toInt(), SQLType.INTEGER.toInt(), SQLType.STRING.toInt()}; 074 075 private static final String SQL_INSERT_TASK_METADATA = "INSERT INTO "+TABLE_TASK_METADATA+" ("+COLUMN_TASK_ID+", "+Definitions.COLUMN_NAME+", "+Definitions.COLUMN_VALUE+", "+COLUMN_ROW_CREATED+") VALUES (?,?,?,NOW())"; 076 private static final int[] SQL_INSERT_TASK_METADATA_TYPES = new int[]{SQLType.LONG.toInt(), SQLType.STRING.toInt(), SQLType.STRING.toInt()}; 077 078 private static final String SQL_SELECT_BACKEND_STATUS_BY_BACKEND_ID = "SELECT "+Definitions.COLUMN_STATUS+", "+COLUMN_MESSAGE+", "+Definitions.COLUMN_BACKEND_ID+" FROM "+TABLE_TASK_BACKENDS+" WHERE "+Definitions.COLUMN_BACKEND_ID+"=? AND "+COLUMN_TASK_ID+"=? LIMIT 1"; 079 private static final int[] SQL_SELECT_BACKEND_STATUS_BY_BACKEND_ID_TYPES = new int[]{SQLType.INTEGER.toInt(), SQLType.LONG.toInt()}; 080 081 private static final String SQL_SELECT_BACKEND_STATUS_BY_TASK_ID = "SELECT "+Definitions.COLUMN_STATUS+", "+COLUMN_MESSAGE+", "+Definitions.COLUMN_BACKEND_ID+" FROM "+TABLE_TASK_BACKENDS+" WHERE "+COLUMN_TASK_ID+"=?"; 082 private static final int[] SQL_SELECT_BACKEND_STATUS_BY_TASK_ID_TYPES = new int[]{SQLType.LONG.toInt()}; 083 084 private static final String SQL_SELECT_BACKEND_STATUS_BY_TASK_STATUS = "SELECT "+Definitions.COLUMN_STATUS+", "+COLUMN_MESSAGE+", "+Definitions.COLUMN_BACKEND_ID+" FROM "+TABLE_TASK_BACKENDS+" WHERE "+Definitions.COLUMN_STATUS+"=? AND "+COLUMN_TASK_ID+"=?"; 085 private static final int[] SQL_SELECT_BACKEND_STATUS_BY_TASK_STATUS_TYPES = new int[]{SQLType.INTEGER.toInt(), SQLType.LONG.toInt()}; 086 087 private static final String SQL_SELECT_TASK_METADATA = "SELECT "+Definitions.COLUMN_NAME+", "+Definitions.COLUMN_VALUE+" FROM "+TABLE_TASK_METADATA+" WHERE "+COLUMN_TASK_ID+"=?"; 088 private static final int[] SQL_SELECT_TASK_METADATA_TYPES = new int[]{SQLType.LONG.toInt()}; 089 090 private static final String SQL_UPDATE_TASK_STATUS = "UPDATE "+TABLE_TASK_BACKENDS+" SET "+Definitions.COLUMN_STATUS+"=?, "+COLUMN_MESSAGE+"=? WHERE "+COLUMN_TASK_ID+"=? AND "+Definitions.COLUMN_BACKEND_ID+"=? LIMIT 1"; 091 private static final int[] SQL_UPDATE_TASK_STATUS_TYPES = new int[]{SQLType.INTEGER.toInt(), SQLType.STRING.toInt(), SQLType.LONG.toInt(), SQLType.INTEGER.toInt()}; 092 093 private static final String SQL_SELECT_TASK_TYPE = "SELECT "+COLUMN_TASK_TYPE+", "+COLUMN_USER_ID+" FROM "+TABLE_TASKS+" WHERE "+COLUMN_TASK_ID+"=?"; 094 private static final int[] SQL_SELECT_TASK_TYPE_TYPES = new int[]{SQLType.LONG.toInt()}; 095 096 private static final String SQL_SELECT_TASK_TYPE_BY_BACKEND_ID = "SELECT "+TABLE_TASKS+"."+COLUMN_TASK_TYPE+", "+COLUMN_USER_ID+" FROM "+TABLE_TASKS+" INNER JOIN "+TABLE_TASK_BACKENDS+" ON "+TABLE_TASKS+"."+COLUMN_TASK_ID+"="+TABLE_TASK_BACKENDS+"."+COLUMN_TASK_ID+" WHERE "+TABLE_TASK_BACKENDS+"."+Definitions.COLUMN_BACKEND_ID+"=? AND "+TABLE_TASK_BACKENDS+"."+COLUMN_TASK_ID+"=? LIMIT 1"; 097 private static final int[] SQL_SELECT_TASK_TYPE_BY_BACKEND_ID_TYPES = new int[]{SQLType.INTEGER.toInt(), SQLType.LONG.toInt()}; 098 099 @Autowired 100 private BackendDAO _backendDAO = null; 101 102 /** 103 * 104 * @param taskId 105 * @param taskStatus optional status filter, if null all back-ends matching the given id will be returned 106 * @return list of back-ends associated with the given taskId 107 */ 108 public BackendStatusList getBackendStatus(Long taskId, TaskStatus taskStatus){ 109 List<Map<String, Object>> rows = null; 110 if(taskStatus == null){ 111 rows = getJdbcTemplate().queryForList(SQL_SELECT_BACKEND_STATUS_BY_TASK_ID, new Object[]{taskId}, SQL_SELECT_BACKEND_STATUS_BY_TASK_ID_TYPES); 112 }else{ 113 rows = getJdbcTemplate().queryForList(SQL_SELECT_BACKEND_STATUS_BY_TASK_STATUS, new Object[]{taskStatus.toInt(), taskId}, SQL_SELECT_BACKEND_STATUS_BY_TASK_STATUS_TYPES); 114 } 115 116 if(rows.isEmpty()){ 117 return null; 118 }else{ 119 BackendStatusList list = new BackendStatusList(); 120 for(Iterator<Map<String,Object>> iter = rows.iterator(); iter.hasNext();){ 121 BackendStatus backendStatus = extractBackendStatus(iter.next()); 122 if(backendStatus == null){ 123 LOGGER.warn("Ignored non-existing back-end."); 124 }else{ 125 list.setBackendStatus(backendStatus); 126 } 127 } 128 if(BackendStatusList.isEmpty(list)){ 129 LOGGER.warn("No valid backends for task, id: "+taskId); 130 return null; 131 }else{ 132 return list; 133 } // else 134 } // else 135 } 136 137 /** 138 * extract new BackendStatus from the given row 139 * 140 * @param row 141 * @return status extracted from the given row map 142 */ 143 private BackendStatus extractBackendStatus(Map<String, Object> row){ 144 BackendStatus s = new BackendStatus(); 145 for(Entry<String, Object> e : row.entrySet()){ 146 switch (e.getKey()) { 147 case Definitions.COLUMN_BACKEND_ID: 148 AnalysisBackend end = _backendDAO.getBackend((Integer)e.getValue()); 149 if(end == null){ 150 LOGGER.warn("Detected non-existent backend."); 151 return null; 152 } 153 s.setBackend(end); 154 break; 155 case Definitions.COLUMN_STATUS: 156 s.setStatus(TaskStatus.fromInt((Integer)e.getValue())); 157 break; 158 case COLUMN_MESSAGE: 159 s.setMessage((String) e.getValue()); 160 break; 161 case COLUMN_GUID: // valid column, but not handled by extractor 162 case COLUMN_TASK_ID: // valid column, but not handled by extractor 163 break; 164 default: 165 throw new IllegalArgumentException("Unhandeled column: "+e.getKey()); 166 } 167 } // for 168 return s; 169 } 170 171 /** 172 * 173 * @param backendId if null, match is made simply by the task id. The parameter can be used to check whether the given back-end is associated with the task id. 174 * @param taskId 175 * @return the task type and task's owner/creator or null if the given task does not exists or if the backend is not set for the task 176 */ 177 protected Pair<TaskType, UserIdentity> getTaskType(Integer backendId, Long taskId) { 178 List<Map<String, Object>> rows = null; 179 if(backendId == null){ 180 LOGGER.debug("Retrieving task type without backend id filter."); 181 rows = getJdbcTemplate().queryForList(SQL_SELECT_TASK_TYPE, new Object[]{taskId}, SQL_SELECT_TASK_TYPE_TYPES); 182 }else{ 183 rows = getJdbcTemplate().queryForList(SQL_SELECT_TASK_TYPE_BY_BACKEND_ID, new Object[]{backendId, taskId}, SQL_SELECT_TASK_TYPE_BY_BACKEND_ID_TYPES); 184 } 185 if(rows.isEmpty()){ 186 LOGGER.warn("Task, id: "+taskId+" was not found for backend, id: "+backendId); 187 return null; 188 } 189 Map<String, Object> row = rows.iterator().next(); 190 Integer taskType = (Integer) row.get(COLUMN_TASK_TYPE); 191 if(taskType == null){ 192 LOGGER.warn("Task, id: "+taskId+" was not found for backend, id: "+backendId); 193 return null; 194 }else{ 195 Long userId = (Long) row.get(COLUMN_USER_ID); 196 return Pair.of(TaskType.fromInt(taskType), (userId == null ? null : new UserIdentity(userId))); 197 } 198 } 199 200 201 /** 202 * 203 * @param details 204 */ 205 protected void insertTaskBackends(AbstractTaskDetails details){ 206 BackendStatusList statuses = details.getBackends(); 207 if(statuses == null){ 208 LOGGER.debug("No backendStatusList, creating a new one..."); 209 statuses = new BackendStatusList(); 210 } 211 212 Integer backendId = details.getBackendId(); 213 if(backendId != null){ 214 BackendStatus s = statuses.getBackendStatus(backendId); 215 if(s == null){ // make sure the back-end of the task is in the status list 216 LOGGER.debug("BackendId was given, inserting backend to the list of target backends with TaskStatus: "+TaskStatus.NOT_STARTED.name()); 217 s = new BackendStatus(new AnalysisBackend(backendId), TaskStatus.NOT_STARTED); 218 statuses.setBackendStatus(s); 219 } 220 } 221 222 Object[] values = new Object[]{details.getTaskId(), null, null, null}; 223 224 if(BackendStatusList.isEmpty(statuses)){ 225 LOGGER.warn("No backends given, the task may not start properly. Task, id: "+values[0]); 226 return; 227 } 228 229 JdbcTemplate t = getJdbcTemplate(); 230 for(BackendStatus s : statuses.getBackendStatuses()){ 231 values[1] = s.getBackendId(); 232 values[2] = s.getStatus().toInt(); 233 values[3] = s.getMessage(); 234 t.update(SQL_INSERT_TASK_BACKEND, values, SQL_INSERT_TASK_BACKEND_TYPES); 235 } 236 } 237 238 /** 239 * 240 * @param details 241 */ 242 protected void getBackendStatusList(AbstractTaskDetails details) { 243 Long taskId = details.getTaskId(); 244 List<Map<String, Object>> rows = getJdbcTemplate().queryForList(SQL_GET_BACKEND_STATUSES, new Object[]{taskId}, SQL_GET_BACKEND_STATUSES_SQL_TYPES); 245 if(rows.isEmpty()){ 246 LOGGER.warn("No back-end for task, id: "+taskId); 247 }else{ 248 BackendStatusList statuses = new BackendStatusList(); 249 for(Map<String, Object> row : rows){ 250 statuses.setBackendStatus(extractBackendStatus(row)); 251 } 252 details.setBackends(statuses); 253 } 254 } 255 256 /** 257 * Update the given status list for the given task. 258 * 259 * @param status 260 * @param taskId 261 */ 262 public void updateTaskStatus(BackendStatusList status, Long taskId){ 263 if(BackendStatusList.isEmpty(status)){ 264 LOGGER.debug("Status list was empty for task, id: "+taskId); 265 return; 266 } 267 for(BackendStatus s : status.getBackendStatuses()){ 268 updateTaskStatus(s, taskId); 269 } 270 } 271 272 /** 273 * 274 * @param backendId 275 * @param taskId 276 * @return the task status for the given backend for the given task, or null if no such task is given for the backend 277 */ 278 public BackendStatus getBackendStatus(Integer backendId, Long taskId){ 279 List<Map<String, Object>> rows = getJdbcTemplate().queryForList(SQL_SELECT_BACKEND_STATUS_BY_BACKEND_ID, new Object[]{backendId, taskId}, SQL_SELECT_BACKEND_STATUS_BY_BACKEND_ID_TYPES); 280 if(rows.isEmpty()){ 281 return null; 282 }else{ 283 return extractBackendStatus(rows.get(0)); 284 } 285 } 286 287 /** 288 * @param backendId 289 * @param dataGroups optional dataGroups filter, if not given, default backend-specific datagroups will be used 290 * @param limits optional limits filter 291 * @param taskId 292 * @return the task or null if not found 293 * @throws IllegalArgumentException on bad values 294 */ 295 public AbstractTaskDetails getTask(Integer backendId, DataGroups dataGroups, Limits limits, Long taskId) throws IllegalArgumentException{ 296 Pair<TaskType, UserIdentity> type = getTaskType(backendId, taskId); 297 if(type == null){ 298 LOGGER.warn("Failed to resolve task type."); 299 return null; 300 } 301 302 if(backendId == null){ 303 LOGGER.debug("No backend id given, will not check data groups."); 304 }else if(DataGroups.isEmpty(dataGroups)){ 305 LOGGER.debug("No datagroups given, retrieving default data groups."); 306 AnalysisBackend backend = _backendDAO.getBackend(backendId); 307 if(backend == null){ 308 throw new IllegalArgumentException("Backend, id: "+backendId+" does not exist."); 309 } 310 dataGroups = backend.getDefaultTaskDataGroups(); 311 } 312 313 AbstractTaskDetailsImpl details = new AbstractTaskDetailsImpl(type.getLeft()); 314 details.setBackendId(backendId); 315 details.setTaskId(taskId); 316 details.setUserId(type.getRight()); 317 318 getTaskMetadata(details); 319 320 if(DataGroups.hasDataGroup(Definitions.DATA_GROUP_BACKEND_STATUS, dataGroups)){ 321 getBackendStatusList(details); 322 } 323 324 return details; 325 } 326 327 /** 328 * Update the given status for the given task. If the status does not previously exist for this backend, new database entry is automatically created. 329 * 330 * @param status 331 * @param taskId 332 */ 333 public void updateTaskStatus(final BackendStatus status, final Long taskId){ 334 getTransactionTemplate().execute(new TransactionCallback<Void>() { 335 336 @Override 337 public Void doInTransaction(TransactionStatus s) { 338 JdbcTemplate t = getJdbcTemplate(); 339 Integer backendId = status.getBackendId(); 340 if(t.queryForObject(SQL_CHECK_TASK_BACKEND, new Object[]{backendId, taskId}, SQL_CHECK_TASK_BACKEND_TYPES, Long.class) > 0){ // already exists 341 if(t.update(SQL_UPDATE_TASK_STATUS, new Object[]{status.getStatus().toInt(), status.getMessage(), taskId, status.getBackendId()}, SQL_UPDATE_TASK_STATUS_TYPES) != 1){ 342 LOGGER.debug("Nothing updated for task, id: "+taskId+", backend, id: "+status.getBackendId()); 343 } 344 }else{ // add new status 345 t.update(SQL_INSERT_TASK_BACKEND, new Object[]{backendId, status.getStatus().toInt(), status.getMessage()}, SQL_INSERT_TASK_BACKEND_TYPES); 346 } 347 return null; 348 } 349 }); 350 } // updateTaskStatus 351 352 /** 353 * This will create the basic task and insert metadata and back-ends 354 * 355 * @param details 356 * @return created row id or null on failure 357 * @throws IllegalArgumentException 358 */ 359 public Long insertTask(AbstractTaskDetails details) throws IllegalArgumentException{ 360 TaskType type = details.getTaskType(); 361 if(type == null){ 362 throw new IllegalArgumentException("No task type given."); 363 } 364 SimpleJdbcInsert taskInsert = new SimpleJdbcInsert(getJdbcTemplate()); 365 taskInsert.withTableName(TABLE_TASKS); 366 taskInsert.setGeneratedKeyName(COLUMN_TASK_ID); 367 taskInsert.usingColumns(SQL_COLUMNS_INSERT_TASK); 368 taskInsert.withoutTableColumnMetaDataAccess(); 369 370 HashMap<String, Object> parameters = new HashMap<>(SQL_COLUMNS_INSERT_TASK.length); 371 parameters.put(COLUMN_TASK_TYPE, type.toInt()); 372 parameters.put(COLUMN_ROW_CREATED, null); 373 parameters.put(COLUMN_USER_ID, details.getUserIdValue()); 374 Number key = taskInsert.executeAndReturnKey(parameters); 375 if(key == null){ 376 LOGGER.error("Failed to add new task."); 377 return null; 378 } 379 380 Long taskId = key.longValue(); 381 details.setTaskId(taskId); 382 383 insertTaskMetadata(details); 384 insertTaskParameters(details); 385 insertTaskBackends(details); 386 387 return taskId; 388 } 389 390 /** 391 * 392 * @param details 393 */ 394 protected void insertTaskParameters(AbstractTaskDetails details){ 395 TaskParameters params = details.getTaskParameters(); 396 if(params == null){ 397 LOGGER.debug("No task parameters."); 398 return; 399 } 400 401 Long taskId = details.getTaskId(); 402 Map<String, String> metadata = params.toMetadata(); 403 if(metadata == null || metadata.isEmpty()){ 404 LOGGER.debug("No task parameter metadata for task, id: "+taskId); 405 }else{ 406 metadata.put(METADATA_TASK_PARAMETER_CLASS, params.getClass().getName()); 407 insertTaskMetadata(metadata, taskId); 408 } 409 } 410 411 /** 412 * 413 * @param details 414 */ 415 protected void insertTaskMetadata(AbstractTaskDetails details){ 416 Long taskId = details.getTaskId(); 417 Map<String, String> metadata = details.getMetadata(); 418 if(metadata == null || metadata.isEmpty()){ 419 LOGGER.debug("No metadata for task, id: "+taskId); 420 }else{ 421 insertTaskMetadata(metadata, taskId); 422 } 423 } 424 425 /** 426 * 427 * @param metadata 428 * @param taskId 429 */ 430 private void insertTaskMetadata(Map<String, String> metadata, Long taskId) { 431 JdbcTemplate t = getJdbcTemplate(); 432 Object[] ob = {taskId, null, null}; 433 for(Entry<String, String> e : metadata.entrySet()){ 434 ob[1] = e.getKey(); 435 ob[2] = e.getValue(); 436 t.update(SQL_INSERT_TASK_METADATA, ob, SQL_INSERT_TASK_METADATA_TYPES); 437 } 438 } 439 440 /** 441 * Retrieves (and sets) the task metadata for the given details. 442 * 443 * This will also retrieve task parameters {@link service.tut.pori.contentanalysis.AbstractTaskDetails#getTaskParameters()} as they are in the default implementation stored in the metadata table. 444 * 445 * @param details 446 * @see #getTaskParameters(AbstractTaskDetails, Map) 447 */ 448 protected void getTaskMetadata(AbstractTaskDetails details){ 449 Long taskId = details.getTaskId(); 450 List<Map<String,Object>> rows = getJdbcTemplate().queryForList(SQL_SELECT_TASK_METADATA, new Object[]{taskId}, SQL_SELECT_TASK_METADATA_TYPES); 451 int count = rows.size(); 452 if(count < 1){ 453 LOGGER.debug("No metadata for task, id: "+taskId); 454 return; 455 } 456 457 HashMap<String, String> metadata = new HashMap<>(count); 458 for(Map<String, Object> row : rows){ 459 metadata.put((String) row.get(Definitions.COLUMN_NAME), (String) row.get(Definitions.COLUMN_VALUE)); 460 } // for 461 details.setMetadata(metadata); 462 463 getTaskParameters(details, metadata); 464 } 465 466 /** 467 * 468 * @param details 469 * @param metadata 470 * @throws IllegalArgumentException on invalid class name 471 */ 472 protected void getTaskParameters(AbstractTaskDetails details, Map<String, String> metadata) throws IllegalArgumentException { 473 String clsName = metadata.get(METADATA_TASK_PARAMETER_CLASS); 474 if(StringUtils.isBlank(clsName)){ 475 LOGGER.debug("No task parameters for task, id: "+details.getTaskId()); 476 return; 477 } 478 479 try { 480 TaskParameters params = (TaskParameters) Class.forName(clsName).newInstance(); 481 params.initialize(metadata); 482 details.setTaskParameters(params); 483 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) { 484 LOGGER.error(ex, ex); 485 throw new IllegalArgumentException("Unknown parameter class : "+clsName); 486 } 487 } 488 489 /** 490 * Basic implementation for Task details 491 * 492 */ 493 private class AbstractTaskDetailsImpl extends AbstractTaskDetails { 494 private TaskParameters _taskParameters = null; 495 496 /** 497 * 498 * @param taskType 499 */ 500 public AbstractTaskDetailsImpl(TaskType taskType) { 501 setTaskType(taskType); 502 } 503 504 @Override 505 public TaskParameters getTaskParameters() { 506 return _taskParameters; 507 } 508 509 @Override 510 public void setTaskParameters(TaskParameters parameters) { 511 _taskParameters = parameters; 512 } 513 } // class AbstractTaskDetailsImpl 514}