Skip to content
This repository has been archived by the owner on Dec 11, 2024. It is now read-only.

Fix for issues with lastUpdated and dateCreated #98

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ web-app
*.log
*.zip
plugin.xml
/docs
/docs
.DS_Store
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import org.codehaus.groovy.runtime.DefaultGroovyMethods
import org.elasticsearch.action.get.GetRequest
import org.elasticsearch.action.get.GetResponse
import org.elasticsearch.client.Client
import org.elasticsearch.common.joda.time.DateTime
import org.elasticsearch.common.xcontent.XContentBuilder
import org.elasticsearch.search.SearchHit
import org.elasticsearch.search.SearchHits
Expand All @@ -37,6 +38,7 @@ import org.springframework.beans.TypeConverter
import org.springframework.util.Assert

import java.beans.PropertyEditor
import java.text.SimpleDateFormat

/**
* Domain class unmarshaller.
Expand Down Expand Up @@ -94,15 +96,30 @@ class DomainClassUnmarshaller {
}
}
new DatabindingApi().setProperties(instance, rebuiltProperties)
populateUnboundDateTimeProperties(instance, rebuiltProperties)

results << instance
}
results
}

private void populateCyclicReference(instance, Map<String, Object> rebuiltProperties, DefaultUnmarshallingContext unmarshallingContext) {
for (CycleReferenceSource cr : unmarshallingContext.cycleRefStack) {
populateProperty(cr.cyclePath, rebuiltProperties, resolvePath(cr.sourcePath, instance, rebuiltProperties))
private void populateUnboundDateTimeProperties(GroovyObject instance, Map<String, Object> rebuiltProperties){
for(Map.Entry<String, Object> entry: rebuiltProperties.entrySet()){

if(instance.hasProperty(entry.key) && !instance.getProperty(entry.key) && entry.value) {

if(instance.hasProperty(entry.key).type.simpleName == DateTime.simpleName){

instance."${entry.key}" = Class.forName(instance.hasProperty(entry.key).type.canonicalName, true, getClass().classLoader).parse(entry.value)
// the above hack is necessary because ElasticSearch has Joda classes under "org.elasticsearch..." package. So,
// if we tried converting the string value into a DateTime using instance."${entry.key}" = DateTime.parse(entry.value),
// we might run into trouble, since instance."${entry.key}" could evaluate to org.joda.DateTime, whereas
// DateTime.parse(entry.value) could evaluate to org.elasticsearch.DateTime
}
else if(instance.hasProperty(entry.key).type == Date && entry.value instanceof Date){
instance."${entry.key}" = entry.value
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package org.grails.plugins.elasticsearch.conversion.unmarshall

import grails.test.mixin.TestMixin
import grails.test.mixin.web.ControllerUnitTestMixin
import org.elasticsearch.common.joda.time.DateTime
import spock.lang.Specification

import java.text.SimpleDateFormat

@TestMixin(ControllerUnitTestMixin)
class DomainClassUnmarshallerSpec extends Specification {

DomainClassUnmarshaller unmarshaller

def setup(){
unmarshaller = new DomainClassUnmarshaller()
}

def "when instance is empty and rebuiltProperties is empty, populateUnboundDateTimeProperties sets nothing"(){
given:
def instance = new Sample()
def rebuiltProperties = [:]

when:
unmarshaller.populateUnboundDateTimeProperties(instance, rebuiltProperties)

then:
instance
!instance.identifier
!instance.phone
!instance.dateCreated
!instance.lastUpdated
}

def "when instance is empty and rebuiltProperties only has properties that do not belong to the instance, populateUnboundDateTimeProperties sets nothing"(){
given:
def instance = new Sample()
def rebuiltProperties = [name: "value", other: "value"]

when:
unmarshaller.populateUnboundDateTimeProperties(instance, rebuiltProperties)

then:
instance
!instance.identifier
!instance.phone
!instance.dateCreated
!instance.lastUpdated
}

def "when instance is empty and rebuiltProperties only has properties that are not date related, populateUnboundDateTimeProperties sets nothing"(){
given:
def instance = new Sample()
def rebuiltProperties = [identifier: "value", phone: "1234567890"]

when:
unmarshaller.populateUnboundDateTimeProperties(instance, rebuiltProperties)

then:
instance
!instance.identifier
!instance.phone
!instance.dateCreated
!instance.lastUpdated
}

def "when instance is empty and rebuiltProperties has properties that are DateTime, populateUnboundDateTimeProperties sets only those dates"(){
given:
def dateCreated = DateTime.now()
def lastUpdated = DateTime.now()
def instance = new Sample()
def rebuiltProperties = [identifier: "value", phone: "1234567890", dateCreated: dateCreated.toString(), lastUpdated: lastUpdated.toString()]

when:
unmarshaller.populateUnboundDateTimeProperties(instance, rebuiltProperties)

then:
instance
!instance.identifier
!instance.phone
dateCreated == instance.dateCreated
lastUpdated == instance.lastUpdated
}

def "when instance is empty and rebuiltProperties has properties that are DateTime and Date, populateUnboundDateTimeProperties sets both types of dates"(){
given:
def dateCreated = DateTime.now()
def lastUpdated = DateTime.now()
def lastSync = new Date()
def instance = new Sample()
def rebuiltProperties = [identifier: "value", phone: "1234567890", dateCreated: dateCreated.toString(), lastUpdated: lastUpdated.toString(), lastSync: lastSync]

when:
unmarshaller.populateUnboundDateTimeProperties(instance, rebuiltProperties)

then:
instance
!instance.identifier
!instance.phone
dateCreated == instance.dateCreated
lastUpdated == instance.lastUpdated
lastSync == instance.lastSync
}

def "when instance is empty and rebuiltProperties has null properties that are DateTime, populateUnboundDateTimeProperties sets only the non-null dates"(){
given:
def dateCreated = DateTime.now()
def instance = new Sample()
def rebuiltProperties = [identifier: "value", phone: "1234567890", dateCreated: dateCreated.toString(), lastUpdated: null]

when:
unmarshaller.populateUnboundDateTimeProperties(instance, rebuiltProperties)

then:
instance
!instance.identifier
!instance.phone
dateCreated == instance.dateCreated
!instance.lastUpdated
}

def "when instance is has date properties, populateUnboundDateTimeProperties does not reset them"(){
given:
def dateCreated = DateTime.now()
def lastUpdated = DateTime.now()
def lastSync = new Date()
def instance = new Sample(dateCreated: dateCreated, lastUpdated: lastUpdated, lastSync: lastSync)
def rebuiltProperties = [identifier: "value", phone: "1234567890", dateCreated: DateTime.now().toString(), lastUpdated: DateTime.now().toString()]

when:
unmarshaller.populateUnboundDateTimeProperties(instance, rebuiltProperties)

then:
instance
!instance.identifier
!instance.phone
dateCreated == instance.dateCreated
lastUpdated == instance.lastUpdated
lastSync == instance.lastSync
}


class Sample {

Long identifier
String phone
DateTime dateCreated
DateTime lastUpdated
Date lastSync

}

}