| Conditions | 72 |
| Total Lines | 405 |
| Code Lines | 268 |
| Lines | 85 |
| Ratio | 20.99 % |
| Changes | 9 | ||
| Bugs | 1 | Features | 3 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like unicon.matthews.xapi.service.DefaultXapiToCaliperConversionService.fromXapi(Statement) often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | /** |
||
| 201 | public Event fromXapi(Statement statement) { |
||
| 202 | // EVENT TIME |
||
| 203 | LocalDateTime eventTime = null; |
||
| 204 | String timestamp = statement.getTimestamp(); |
||
| 205 | if (StringUtils.isNotBlank(timestamp)) { |
||
| 206 | if (timestamp.endsWith("Z")) { |
||
| 207 | Instant instant = Instant.parse(timestamp); |
||
| 208 | eventTime = LocalDateTime.ofInstant(instant, ZoneId.of(ZoneOffset.UTC.getId())); |
||
| 209 | } |
||
| 210 | else { |
||
| 211 | ZonedDateTime zdt = ZonedDateTime.parse(timestamp); |
||
| 212 | ZonedDateTime utc_zone = zdt.toLocalDateTime().atZone(ZoneOffset.UTC); |
||
| 213 | eventTime = utc_zone.toLocalDateTime(); |
||
| 214 | } |
||
| 215 | |||
| 216 | } |
||
| 217 | else { |
||
| 218 | eventTime = LocalDateTime.now(ZoneId.of(ZoneOffset.UTC.getId())); |
||
| 219 | } |
||
| 220 | // EVENT TIME END |
||
| 221 | |||
| 222 | // ACTOR |
||
| 223 | Agent caliperActor = null; |
||
| 224 | String actorId = null; |
||
| 225 | XApiActor xapiActor = statement.getActor(); |
||
| 226 | if (xapiActor != null) { |
||
| 227 | |||
| 228 | String actorType = null; |
||
| 229 | Map<String, String> actorExtensions = new HashMap<>(); |
||
| 230 | String actorName = xapiActor.getName(); |
||
| 231 | |||
| 232 | String openId = xapiActor.getOpenid(); |
||
| 233 | String mbox = xapiActor.getMbox(); |
||
| 234 | XApiAccount xapiAccount = xapiActor.getAccount(); |
||
| 235 | |||
| 236 | if (StringUtils.isNotBlank(openId)) { |
||
| 237 | actorId = openId; |
||
| 238 | actorType = ACTOR_TYPE_OPENID; |
||
| 239 | } |
||
| 240 | else if (StringUtils.isNotBlank(mbox)) { |
||
| 241 | actorId = mbox; |
||
| 242 | actorType = ACTOR_TYPE_MBOX; |
||
| 243 | } |
||
| 244 | else if (xapiAccount != null) { |
||
| 245 | String accountName = xapiAccount.getName(); |
||
| 246 | String homePage = xapiAccount.getHomePage(); |
||
| 247 | |||
| 248 | if (StringUtils.isNotBlank(homePage)) { |
||
| 249 | |||
| 250 | if (StringUtils.isNotBlank(accountName)) { |
||
| 251 | actorId = accountName; |
||
| 252 | actorExtensions.put("HOMEPAGE", homePage); |
||
| 253 | } |
||
| 254 | else { |
||
| 255 | actorId = homePage; |
||
| 256 | } |
||
| 257 | } |
||
| 258 | else if (StringUtils.isNotBlank(accountName)) { |
||
| 259 | actorId = accountName; |
||
| 260 | } |
||
| 261 | |||
| 262 | actorType = ACTOR_TYPE_ACCOUNT; |
||
| 263 | } |
||
| 264 | |||
| 265 | caliperActor |
||
| 266 | = new Agent.Builder() |
||
| 267 | .withContext(Context.CONTEXT.getValue()) |
||
| 268 | .withName(actorName) |
||
| 269 | .withId(actorId) |
||
| 270 | .withType(actorType) |
||
| 271 | .withExtensions(actorExtensions) |
||
| 272 | .build(); |
||
| 273 | } |
||
| 274 | // ACTOR END |
||
| 275 | |||
| 276 | // RESULT |
||
| 277 | Entity caliperResult = null; |
||
| 278 | XApiResult xapiResult = statement.getResult(); |
||
| 279 | if (xapiResult != null) { |
||
| 280 | Map<String,String> resultExtensions = null; |
||
| 281 | Map<URI,java.lang.Object> xapiResultExtensions = xapiResult.getExtensions(); |
||
| 282 | if (xapiResultExtensions != null && !xapiResultExtensions.isEmpty()) { |
||
| 283 | resultExtensions = new HashMap<>(); |
||
| 284 | for (Map.Entry<URI,java.lang.Object> entry : xapiResultExtensions.entrySet()) { |
||
| 285 | resultExtensions.put(entry.getKey().toString(),entry.getValue().toString()); |
||
| 286 | } |
||
| 287 | } |
||
| 288 | |||
| 289 | Double score = null; |
||
| 290 | XApiScore xapiScore = xapiResult.getScore(); |
||
| 291 | if (xapiScore != null) { |
||
| 292 | score = xapiScore.getRaw(); |
||
| 293 | } |
||
| 294 | |||
| 295 | caliperResult |
||
| 296 | = new Entity.Builder() |
||
| 297 | .withId(UUID.randomUUID().toString()) |
||
| 298 | .withContext(Context.CONTEXT.getValue()) |
||
| 299 | .withExtensions(resultExtensions) |
||
| 300 | .withActor(actorId) |
||
| 301 | .withType("http://purl.imsglobal.org/caliper/v1/Result") |
||
| 302 | .withTotalScore(score) |
||
| 303 | .build(); |
||
| 304 | } |
||
| 305 | // END Result |
||
| 306 | |||
| 307 | // ACTION |
||
| 308 | String caliperAction = null; |
||
| 309 | XApiVerb xapiVerb = statement.getVerb(); |
||
| 310 | if (xapiVerb != null) { |
||
| 311 | String verbId = xapiVerb.getId(); |
||
| 312 | caliperAction = xApiVerbToCaliperAction(verbId); |
||
| 313 | } |
||
| 314 | // ACTION END |
||
| 315 | |||
| 316 | // OBJECT |
||
| 317 | Entity caliperObject = null; |
||
| 318 | XApiObject xapiObject = statement.getObject(); |
||
| 319 | if (xapiObject != null) { |
||
| 320 | |||
| 321 | String objectType = xapiObjectTypeToCaliperEntityType(null); |
||
| 322 | String objectName = null; |
||
| 323 | String objectDescription = null; |
||
| 324 | Map<String,String> objectExtensions = null; |
||
| 325 | String objectId = xapiObject.getId(); |
||
| 326 | |||
| 327 | XApiObjectDefinition xapiObjectDefinition = xapiObject.getDefinition(); |
||
| 328 | if (xapiObjectDefinition != null) { |
||
| 329 | String xapiObjectDefinitionType = xapiObjectDefinition.getType(); |
||
| 330 | if (StringUtils.isNotBlank(xapiObjectDefinitionType)) { |
||
| 331 | objectType = xapiObjectTypeToCaliperEntityType(xapiObjectDefinitionType); |
||
| 332 | } |
||
| 333 | |||
| 334 | Map<String,String> names = xapiObjectDefinition.getName(); |
||
| 335 | if (names != null) { |
||
| 336 | if (names.size() == 1) { |
||
| 337 | objectName = CollectionUtils.get(names, 0).getValue(); |
||
| 338 | } |
||
| 339 | else { |
||
| 340 | // default to en? |
||
| 341 | objectName = names.get("en"); |
||
| 342 | } |
||
| 343 | } |
||
| 344 | |||
| 345 | Map<String,String> descriptions = xapiObjectDefinition.getDescription(); |
||
| 346 | if (descriptions != null) { |
||
| 347 | if (descriptions.size() == 1) { |
||
| 348 | objectDescription = CollectionUtils.get(descriptions, 0).getValue(); |
||
| 349 | } |
||
| 350 | else { |
||
| 351 | // default to en? |
||
| 352 | objectDescription = descriptions.get("en"); |
||
| 353 | } |
||
| 354 | } |
||
| 355 | |||
| 356 | Map<URI,java.lang.Object> extensions = xapiObjectDefinition.getExtensions(); |
||
| 357 | if (extensions != null && !extensions.isEmpty()) { |
||
| 358 | objectExtensions = new HashMap<String,String>(extensions.size()); |
||
| 359 | for (URI key : extensions.keySet()) { |
||
| 360 | objectExtensions.put(key.toString(), extensions.get(key).toString()); |
||
| 361 | } |
||
| 362 | } |
||
| 363 | } |
||
| 364 | |||
| 365 | caliperObject |
||
| 366 | = new Entity.Builder() |
||
| 367 | .withId(objectId) |
||
| 368 | .withContext(Context.CONTEXT.getValue()) |
||
| 369 | .withType(objectType) |
||
| 370 | .withName(objectName) |
||
| 371 | .withDescription(objectDescription) |
||
| 372 | .withExtensions(objectExtensions) |
||
| 373 | .build(); |
||
| 374 | } |
||
| 375 | // OBJECT END |
||
| 376 | |||
| 377 | Group caliperGroup = null; |
||
| 378 | XApiContext xapiContext = statement.getContext(); |
||
| 379 | if (xapiContext != null) { |
||
| 380 | Map<String,String> contextExtensions = null; |
||
| 381 | Map<URI,java.lang.Object> extensions = xapiContext.getExtensions(); |
||
| 382 | if (extensions != null && !extensions.isEmpty()) { |
||
| 383 | contextExtensions = new HashMap<String,String>(extensions.size()); |
||
| 384 | for (URI key : extensions.keySet()) { |
||
| 385 | contextExtensions.put(key.toString(), extensions.get(key).toString()); |
||
| 386 | } |
||
| 387 | } |
||
| 388 | |||
| 389 | XApiContextActivities xapiContextActivities = xapiContext.getContextActivities(); |
||
| 390 | if (xapiContextActivities != null) { |
||
| 391 | List<XApiObject> contextActivityParents = xapiContextActivities.getParent(); |
||
| 392 | |||
| 393 | if (contextActivityParents != null && contextActivityParents.size() == 1 |
||
| 394 | && contextActivityParents.get(0).getId().contains("portal/site")) { |
||
| 395 | caliperGroup |
||
| 396 | = new Group.Builder() |
||
| 397 | .withId(StringUtils.substringAfterLast(contextActivityParents.get(0).getId(), "/")) |
||
| 398 | .withContext(Context.CONTEXT.getValue()) |
||
| 399 | .withType("http://purl.imsglobal.org/caliper/v1/lis/CourseSection") |
||
| 400 | .build(); |
||
| 401 | } |
||
| 402 | |||
| 403 | if (caliperGroup == null) { |
||
| 404 | List<XApiObject> groupings = xapiContextActivities.getGrouping(); |
||
| 405 | if (groupings != null && !groupings.isEmpty()) { |
||
| 406 | XApiObject grouping = null; |
||
| 407 | String id = null; |
||
| 408 | String type = null; |
||
| 409 | |||
| 410 | if (groupings.size() == 1) { |
||
| 411 | grouping = groupings.get(0); |
||
| 412 | |||
| 413 | if (extensions != null) { |
||
| 414 | Object paramMap = null; |
||
| 415 | try { |
||
| 416 | paramMap = extensions.get(new URI("http://lrs.learninglocker.net/define/extensions/moodle_logstore_standard_log")); |
||
| 417 | } |
||
| 418 | catch (URISyntaxException e) { |
||
| 419 | // TODO |
||
| 420 | } |
||
| 421 | if (paramMap != null && paramMap instanceof Map) { |
||
| 422 | Map<String, String> groupExtMap = (Map<String, String>)paramMap; |
||
| 423 | id = groupExtMap.get("courseid"); |
||
| 424 | type = "http://purl.imsglobal.org/caliper/v1/lis/CourseSection"; |
||
| 425 | } |
||
| 426 | } |
||
| 427 | } |
||
| 428 | else { |
||
| 429 | for (XApiObject xo : groupings) { |
||
| 430 | grouping = xo; |
||
| 431 | XApiObjectDefinition xapiObjectDefinition = xo.getDefinition(); |
||
| 432 | if (xapiObjectDefinition != null) { |
||
| 433 | if ("http://lrs.learninglocker.net/define/type/moodle/course".equals(xapiObjectDefinition.getType())) { |
||
| 434 | type = "http://purl.imsglobal.org/caliper/v1/lis/CourseSection"; |
||
| 435 | Map<URI, Object> groupExt = xapiObjectDefinition.getExtensions(); |
||
| 436 | if (groupExt != null) { |
||
| 437 | try { |
||
| 438 | Object paramMap = groupExt.get(new URI("http://lrs.learninglocker.net/define/extensions/moodle_course")); |
||
| 439 | if (paramMap instanceof Map) { |
||
| 440 | Map<String, String> groupExtMap = (Map<String, String>)paramMap; |
||
| 441 | id = groupExtMap.get("id"); |
||
| 442 | } |
||
| 443 | |||
| 444 | } |
||
| 445 | catch (URISyntaxException e) { |
||
| 446 | //TODO |
||
| 447 | } |
||
| 448 | } |
||
| 449 | |||
| 450 | break; |
||
| 451 | } |
||
| 452 | } |
||
| 453 | } |
||
| 454 | } |
||
| 455 | |||
| 456 | if (grouping != null) { |
||
| 457 | String name = null; |
||
| 458 | String description = null; |
||
| 459 | XApiObjectDefinition xapiObjectDefinition = grouping.getDefinition(); |
||
| 460 | if (xapiObjectDefinition != null) { |
||
| 461 | |||
| 462 | if (StringUtils.isBlank(type) && StringUtils.isNoneBlank(xapiObjectDefinition.getType())) { |
||
| 463 | type = xapiObjectDefinition.getType(); |
||
| 464 | } |
||
| 465 | |||
| 466 | Map<String,String> names =xapiObjectDefinition.getName(); |
||
| 467 | if (names != null) { |
||
| 468 | if (names.size() == 1) { |
||
| 469 | name = CollectionUtils.get(names, 0).getValue(); |
||
| 470 | } |
||
| 471 | else { |
||
| 472 | // default to en? |
||
| 473 | name = names.get("en"); |
||
| 474 | } |
||
| 475 | } |
||
| 476 | |||
| 477 | Map<String,String> descriptions = xapiObjectDefinition.getDescription(); |
||
| 478 | if (descriptions != null) { |
||
| 479 | if (descriptions.size() == 1) { |
||
| 480 | description = CollectionUtils.get(descriptions, 0).getValue(); |
||
| 481 | } |
||
| 482 | else { |
||
| 483 | // default to en? |
||
| 484 | description = descriptions.get("en"); |
||
| 485 | } |
||
| 486 | } |
||
| 487 | } |
||
| 488 | |||
| 489 | List<XApiObject> parents = xapiContextActivities.getParent(); |
||
| 490 | SubOrganizationOf subOrganizationOf = null; |
||
| 491 | View Code Duplication | if (parents != null && parents.size() == 1) { |
|
| 492 | XApiObject parent = parents.get(0); |
||
| 493 | String parentId = parent.getId(); |
||
| 494 | String parentType = "http://purl.imsglobal.org/caliper/v1/lis/CourseOffering"; |
||
| 495 | String parentName = null; |
||
| 496 | String parentDescription = null; |
||
| 497 | XApiObjectDefinition parentXapiObjectDefinition = parent.getDefinition(); |
||
| 498 | if (parentXapiObjectDefinition != null) { |
||
| 499 | |||
| 500 | if (StringUtils.isNoneBlank(parentXapiObjectDefinition.getType())) { |
||
| 501 | parentType = parentXapiObjectDefinition.getType(); |
||
| 502 | } |
||
| 503 | |||
| 504 | Map<String,String> names = parentXapiObjectDefinition.getName(); |
||
| 505 | if (names != null) { |
||
| 506 | if (names.size() == 1) { |
||
| 507 | parentName = CollectionUtils.get(names, 0).getValue(); |
||
| 508 | } |
||
| 509 | else { |
||
| 510 | // default to en? |
||
| 511 | parentName = names.get("en"); |
||
| 512 | } |
||
| 513 | } |
||
| 514 | |||
| 515 | Map<String,String> descriptions = parentXapiObjectDefinition.getDescription(); |
||
| 516 | if (descriptions != null) { |
||
| 517 | if (descriptions.size() == 1) { |
||
| 518 | parentDescription = CollectionUtils.get(descriptions, 0).getValue(); |
||
| 519 | } |
||
| 520 | else { |
||
| 521 | // default to en? |
||
| 522 | parentDescription = descriptions.get("en"); |
||
| 523 | } |
||
| 524 | } |
||
| 525 | |||
| 526 | subOrganizationOf |
||
| 527 | = new SubOrganizationOf.Builder() |
||
| 528 | .withId(parentId) |
||
| 529 | .withContext(Context.CONTEXT.getValue()) |
||
| 530 | .withType(parentType) |
||
| 531 | .withName(parentName) |
||
| 532 | .withDescription(parentDescription) |
||
| 533 | .build(); |
||
| 534 | } |
||
| 535 | } |
||
| 536 | |||
| 537 | caliperGroup |
||
| 538 | = new Group.Builder() |
||
| 539 | .withId(id) |
||
| 540 | .withContext(Context.CONTEXT.getValue()) |
||
| 541 | .withType(type) |
||
| 542 | .withName(name) |
||
| 543 | .withDescription(description) |
||
| 544 | .withExtensions(contextExtensions) |
||
| 545 | .withSubOrganizationOf(subOrganizationOf) |
||
| 546 | .build(); |
||
| 547 | } |
||
| 548 | View Code Duplication | else if (xapiContextActivities.getParent() != null) { |
|
| 549 | XApiObject parent = xapiContextActivities.getParent().get(0); |
||
| 550 | String name = null; |
||
| 551 | String description = null; |
||
| 552 | XApiObjectDefinition xapiObjectDefinition = parent.getDefinition(); |
||
| 553 | if (xapiObjectDefinition != null) { |
||
| 554 | if (StringUtils.isBlank(type) && StringUtils.isNoneBlank(xapiObjectDefinition.getType())) { |
||
| 555 | type = xapiObjectDefinition.getType(); |
||
| 556 | } |
||
| 557 | |||
| 558 | Map<String,String> names = xapiObjectDefinition.getName(); |
||
| 559 | if (names != null) { |
||
| 560 | if (names.size() == 1) { |
||
| 561 | name = CollectionUtils.get(names, 0).getValue(); |
||
| 562 | } |
||
| 563 | else { |
||
| 564 | // default to en? |
||
| 565 | name = names.get("en"); |
||
| 566 | } |
||
| 567 | } |
||
| 568 | |||
| 569 | Map<String,String> descriptions = xapiObjectDefinition.getDescription(); |
||
| 570 | if (descriptions != null) { |
||
| 571 | if (descriptions.size() == 1) { |
||
| 572 | description = CollectionUtils.get(descriptions, 0).getValue(); |
||
| 573 | } |
||
| 574 | else { |
||
| 575 | // default to en? |
||
| 576 | description = descriptions.get("en"); |
||
| 577 | } |
||
| 578 | } |
||
| 579 | } |
||
| 580 | |||
| 581 | caliperGroup |
||
| 582 | = new Group.Builder() |
||
| 583 | .withId(parent.getId()) |
||
| 584 | .withContext(Context.CONTEXT.getValue()) |
||
| 585 | .withType(type) |
||
| 586 | .withName(name) |
||
| 587 | .withDescription(description) |
||
| 588 | .withExtensions(contextExtensions) |
||
| 589 | .build(); |
||
| 590 | } |
||
| 591 | } |
||
| 592 | } |
||
| 593 | } |
||
| 594 | } |
||
| 595 | |||
| 596 | return |
||
| 597 | new Event.Builder() |
||
| 598 | .withAction(caliperAction) |
||
| 599 | .withAgent(caliperActor) |
||
| 600 | .withObject(caliperObject) |
||
| 601 | .withEventTime(eventTime) |
||
| 602 | .withContext(xapiToCaliperType(statement)) |
||
| 603 | .withGroup(caliperGroup) |
||
| 604 | .withGenerated(caliperResult) |
||
| 605 | .build(); |
||
| 606 | |||
| 818 |
The Java documentation explain EnumMap.