| | 590 | |
|---|
| | 591 | /** |
|---|
| | 592 | * Populates a Serializable Entity with a new GUID if needed |
|---|
| | 593 | * GUID is assigned under the following circumstances: |
|---|
| | 594 | * - objectGuid is null or "" |
|---|
| | 595 | * and |
|---|
| | 596 | * - if SyncItemState is NEW assign new GUID |
|---|
| | 597 | * - else if SyncItemState != NEW, verify that the GUID doesn't already exist in the DB for the primary key value; |
|---|
| | 598 | * - if it doesn't, assign new GUID |
|---|
| | 599 | * - else fill-in existing GUID |
|---|
| | 600 | * |
|---|
| | 601 | * Note 1: dataChanged is also set to true to let Hibernate know we are changing a record right underneath of it. |
|---|
| | 602 | * |
|---|
| | 603 | * Note 2: verification if GUID already exists for given primary key value is important in preventing inadvertent |
|---|
| | 604 | * data corruption when client code does not retrieve GUID value when updating existing domain object. |
|---|
| | 605 | * For example this following code would result in overriding the GUID for concept_id of 5089: |
|---|
| | 606 | * //update existing concept |
|---|
| | 607 | * Concept wt = new ConceptNumeric(5089); |
|---|
| | 608 | * wt.addName(new ConceptName("WEIGHT (KG)",...) |
|---|
| | 609 | * Context.getConceptService().updateConcept(wt, true); |
|---|
| | 610 | * |
|---|
| | 611 | * In order to avoid all client code having to perform guid retrieval in situations like above, we will do this check here. |
|---|
| | 612 | * |
|---|
| | 613 | * @param entity The object changed. |
|---|
| | 614 | * @param currentState Array containing data for each field in the object as they will be saved. |
|---|
| | 615 | * @param propertyNames Array containing name for each field in the object, corresponding to currentState. |
|---|
| | 616 | * @param types Array containing Type of the field in the object, corresponding to currentState. |
|---|
| | 617 | * @param state SyncItemState, e.g. NEW, UPDATED, DELETED |
|---|
| | 618 | * @param id Value of the identifier for this entity |
|---|
| | 619 | * @return True if data was altered, false otherwise. |
|---|
| | 620 | */ |
|---|
| | 621 | protected boolean assignGUID(Synchronizable entity, Object[] currentState, String[] propertyNames, SyncItemState state) throws SyncException { |
|---|
| | 622 | |
|---|
| | 623 | /* |
|---|
| | 624 | * Clear GUID if it is invalid: if this is save event that is 'local' (i.e. getLastRecordGuid not |
|---|
| | 625 | * yet assigned) *and* GUID is already assigned, clear it out and get a new one: this can happen |
|---|
| | 626 | * is someone does object copy and has incorrect constructor or if object is disconnected from |
|---|
| | 627 | * session and then saved anew; as in obs edit |
|---|
| | 628 | */ |
|---|
| | 629 | if (state == SyncItemState.NEW && entity.getGuid() != null && entity.getLastRecordGuid() == null) { |
|---|
| | 630 | entity.setGuid(null); |
|---|
| | 631 | } |
|---|
| | 632 | |
|---|
| | 633 | // If entity already has a GUID on this server, no need to assign a new one |
|---|
| | 634 | if (StringUtils.hasText(entity.getGuid())) { |
|---|
| | 635 | if (log.isDebugEnabled()) log.debug("Entity: " + entity + " already has a GUID assigned: " + entity.getGuid()); |
|---|
| | 636 | return false; |
|---|
| | 637 | } |
|---|
| | 638 | |
|---|
| | 639 | // Iterate over properties and identify GUID, if it exists |
|---|
| | 640 | for (int i = 0; i < propertyNames.length; i++) { |
|---|
| | 641 | String propName = propertyNames[i]; |
|---|
| | 642 | if ("guid".equalsIgnoreCase(propName)) { |
|---|
| | 643 | String guidToAssign = null; |
|---|
| | 644 | if (state != SyncItemState.NEW) { // attempt to fetch first |
|---|
| | 645 | guidToAssign = this.fetchGuid(entity); |
|---|
| | 646 | } |
|---|
| | 647 | if (StringUtils.hasText(guidToAssign)) { |
|---|
| | 648 | if (log.isDebugEnabled()) log.debug("Assigned GUID to entity: " + entity + " from database GUID: " + guidToAssign); |
|---|
| | 649 | } |
|---|
| | 650 | else { |
|---|
| | 651 | guidToAssign = UUID.randomUUID().toString(); |
|---|
| | 652 | if (log.isDebugEnabled()) log.debug("Assigned newly generated GUID to entity: " + entity + ": " + guidToAssign); |
|---|
| | 653 | } |
|---|
| | 654 | currentState[i] = guidToAssign; |
|---|
| | 655 | return true; |
|---|
| | 656 | } |
|---|
| | 657 | } |
|---|
| | 658 | return false; |
|---|
| | 659 | } |
|---|
| 635 | | |
|---|
| 636 | | /* |
|---|
| 637 | | * Get the GUID of this object if it has one, used as SyncItemKey. |
|---|
| 638 | | * if this is save event that is 'local' (i.e. getLastRecordGuid not |
|---|
| 639 | | * yet assigned) *and* guid is already assigned, clear it out and |
|---|
| 640 | | * get a new one: this can happen is someone does object copy and |
|---|
| 641 | | * has incorrect constructor or if object is disconnected from |
|---|
| 642 | | * session and then saved anew; as in obs edit |
|---|
| 643 | | */ |
|---|
| 644 | | if (state == SyncItemState.NEW && entity.getGuid() != null |
|---|
| 645 | | && entity.getLastRecordGuid() == null) { |
|---|
| 646 | | entity.setGuid(null); |
|---|
| 647 | | } else { |
|---|
| 648 | | objectGuid = entity.getGuid(); |
|---|
| 649 | | } |
|---|
| | 710 | |
|---|
| | 711 | boolean isGuidAssigned = assignGUID(entity, currentState, propertyNames, state); |
|---|
| | 712 | objectGuid = entity.getGuid(); |
|---|
| | 713 | dataChanged = dataChanged || isGuidAssigned; |
|---|
| 720 | | |
|---|
| 721 | | /* |
|---|
| 722 | | * GUID assignment. GUID is assigned under the following circumstances: |
|---|
| 723 | | * - objectGuid is null or "" |
|---|
| 724 | | * and |
|---|
| 725 | | * - if SyncItemState is NEW assign new GUID |
|---|
| 726 | | * - else if SyncItemState != NEW, verify that the guid doesn't already exist in the DB |
|---|
| 727 | | * for the primary key value; |
|---|
| 728 | | * - if it doesn't, assign new GUID |
|---|
| 729 | | * - else fill-in existing GUID |
|---|
| 730 | | * |
|---|
| 731 | | * Note 1: dataChanged is also set to true to let Hibernate know |
|---|
| 732 | | * we are changing a record right underneath of it. |
|---|
| 733 | | * |
|---|
| 734 | | * Note 2: verification if GUID already exists for given primary key value is important in |
|---|
| 735 | | * preventing inadvertent data corruption when client code does not retrieve |
|---|
| 736 | | * GUID value when updating existing domain object. Fro example this following code |
|---|
| 737 | | * would result in overriding the GUID for concept_id of 5089: |
|---|
| 738 | | * //update existing concept |
|---|
| 739 | | * Concept wt = new ConceptNumeric(5089); |
|---|
| 740 | | * wt.addName(new ConceptName("WEIGHT (KG)",...) |
|---|
| 741 | | * Context.getConceptService().updateConcept(wt, true); |
|---|
| 742 | | * |
|---|
| 743 | | * In order to avoid all client code having to perform guid retrieval in situations like |
|---|
| 744 | | * above, we will do this check here. |
|---|
| 745 | | */ |
|---|
| 746 | | if (typeName.equals("string") |
|---|
| 747 | | && propertyNames[i].equals("guid") |
|---|
| 748 | | && (objectGuid == null || objectGuid.equals(""))) { |
|---|
| 749 | | |
|---|
| 750 | | String msg = ""; |
|---|
| 751 | | if (state != SyncItemState.NEW) { // attempt to fetch first |
|---|
| 752 | | objectGuid = this.fetchGuid(entity); |
|---|
| 753 | | msg = ", assigned guid for existing record from DB:"; |
|---|
| 754 | | } |
|---|
| 755 | | |
|---|
| 756 | | if (objectGuid == null || objectGuid.equals("")) { |
|---|
| 757 | | objectGuid = UUID.randomUUID().toString(); |
|---|
| 758 | | msg = ", assigned newly generated guid:"; |
|---|
| 759 | | }; |
|---|
| 760 | | |
|---|
| 761 | | currentState[i] = objectGuid; |
|---|
| 762 | | dataChanged = true; |
|---|
| 763 | | if (log.isInfoEnabled()) |
|---|
| 764 | | log.info(infoMsg + msg + currentState[i]); |
|---|
| 765 | | } |
|---|