Downloads Documentation Community Contribute Demo






Show Sidebar
Login | Register

Changeset 5203

Show
Ignore:
Timestamp:
08/08/08 13:26:25 (3 months ago)
Author:
mseaton
Message:

openmrs-synchronization branch: add guid to every object in interceptor, regardless of synchronization

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • openmrs/branches/data_synchronization_bidirectional/src/api/org/openmrs/api/db/hibernate/HibernateSynchronizationInterceptor.java

    r5201 r5203  
    3333import org.hibernate.CallbackException; 
    3434import org.hibernate.SessionFactory; 
     35import org.springframework.util.StringUtils; 
    3536import org.hibernate.Transaction; 
    3637import org.hibernate.metadata.ClassMetadata; 
     
    371372                        log.debug("onSave: " + state.toString()); 
    372373                 
     374                boolean isGuidAssigned = assignGUID((Synchronizable) entity, state, propertyNames, SyncItemState.NEW); 
     375 
    373376                // explicitly bail out if sync is disabled 
    374377                if (SyncUtil.getSyncStatus() == SyncStatusState.DISABLED_SYNC_AND_HISTORY) 
    375                         return false
     378                        return isGuidAssigned
    376379 
    377380                // first see if entity should be written to the journal at all 
     
    379382                        if (log.isDebugEnabled()) 
    380383                                log.debug("Determined entity not to be journaled, exiting onSave."); 
    381                         return false
     384                        return isGuidAssigned
    382385                } 
    383386 
     
    418421                        log.debug("onFlushDirty: " + entity.getClass().getName()); 
    419422                 
     423                boolean isGuidAssigned = assignGUID((Synchronizable) entity, currentState, propertyNames, SyncItemState.UPDATED); 
     424 
    420425                // explicitly bail out if sync is disabled 
    421426                if (SyncUtil.getSyncStatus() == SyncStatusState.DISABLED_SYNC_AND_HISTORY) 
    422                         return false
     427                        return isGuidAssigned
    423428 
    424429                // first see if entity should be written to the journal at all 
     
    426431                        if (log.isDebugEnabled()) 
    427432                                log.debug("Determined entity not to be journaled, exiting onSave."); 
    428                         return false
     433                        return isGuidAssigned
    429434                } 
    430435 
     
    583588                this.processPersistentSet((PersistentSet) collection, key, "update"); 
    584589        } 
     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        } 
    585660 
    586661        /** 
     
    633708 
    634709                try { 
    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; 
    650714 
    651715                        // pull-out sync-network wide change id, if one was already assigned 
     
    718782                                        log.warn(infoMsg + ", Id for this class: " + idPropertyName 
    719783                                                + " , value:" + currentState[i]); 
    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                                 } 
    766784 
    767785                                if (currentState[i] != null) {