/* * Copyright 2012-2015, the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.flipkart.aesop.relay.sample; import java.util.LinkedList; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import org.codehaus.jackson.map.ObjectMapper; import org.springframework.core.serializer.support.SerializationFailedException; import com.flipkart.aesop.events.sample.person.FieldChange; import com.flipkart.aesop.events.sample.person.Person; import com.flipkart.aesop.serializer.model.UserInfo; import com.flipkart.aesop.serializer.stateengine.DiffChangeEventMapper; import com.netflix.zeno.diff.TypeDiff; import com.netflix.zeno.diff.TypeDiff.ObjectDiffScore; import com.netflix.zeno.genericobject.GenericObject; import com.netflix.zeno.genericobject.GenericObject.Field; import com.netflix.zeno.genericobject.GenericObjectSerializationFramework; import com.netflix.zeno.serializer.SerializerFactory; /** * The <code>PersonDiffChangeEventMapper</code> is an implementation of the {@link DiffChangeEventMapper} that maps {@link com.flipkart.aesop.serializer.model.UserInfo} * data from the state engine to {@link Person} change event instances * * @author Regunath B * @version 1.0, 20 March 2014 */ public class PersonDiffChangeEventMapper implements DiffChangeEventMapper<UserInfo,Person> { /** The ObjectMapper to use for JSON serialization of {@link UserInfo#getPreferences()}, {@link UserInfo#getAddresses()}, {@link UserInfo#getMerged_account_ids()} */ private ObjectMapper objectMapper = new ObjectMapper(); /** * Interface method implementation. Returns the type of {@link com.flipkart.aesop.serializer.model.UserInfo} * @see com.flipkart.aesop.serializer.stateengine.DiffChangeEventMapper#getNFTypeName() */ public String getNFTypeName() { return UserInfo.class.getName(); } /** * Interface method implementation. Returns {@link UserInfo#getId()} * @see com.flipkart.aesop.serializer.stateengine.DiffChangeEventMapper#getTypeKey(java.lang.Object) */ public Object getTypeKey(UserInfo userInfo) { return userInfo.getId(); } /** * Interface method implementation. Returns {@link Person#getKey()} * @see com.flipkart.aesop.serializer.stateengine.DiffChangeEventMapper#getChangeEventKey(org.apache.avro.generic.GenericRecord) */ public Object getChangeEventKey(Person person) { return person.getKey(); // here we are overloading the Person to also act as a change event object for testing } /** * Interface method implementation. Returns {@link System#currentTimeMillis()} for testing * @see com.flipkart.aesop.serializer.stateengine.DiffChangeEventMapper#getSequenceId(org.apache.avro.generic.GenericRecord) */ public Long getSequenceId(Person changeEvent) { return System.currentTimeMillis(); } /** * Interface method implementation. Returns a List of {@link Person} instances derived from data contained in the specified {@link TypeDiff} containing * diff information on {@link UserInfo} objects * @see com.flipkart.aesop.serializer.stateengine.DiffChangeEventMapper#getChangeEvents(com.netflix.zeno.diff.TypeDiff) */ public List<Person> getChangeEvents(TypeDiff<UserInfo> typeDiff, SerializerFactory serializerFactory) { List<Person> personsList = new LinkedList<Person>(); GenericObjectSerializationFramework genericObjectFramework = new GenericObjectSerializationFramework(serializerFactory); for(ObjectDiffScore<UserInfo> objectDiff : typeDiff.getDiffObjects()) { GenericObject fromGenericObject = genericObjectFramework.serialize(objectDiff.getFrom(), this.getNFTypeName()); GenericObject toGenericObject = genericObjectFramework.serialize(objectDiff.getTo(), this.getNFTypeName()); List<FieldChange> fieldChanges = new LinkedList<FieldChange>(); for(int i=0;i<fromGenericObject.getFields().size();i++) { Field fromField = fromGenericObject.getFields().get(i); Field toField = toGenericObject.getFields().get(i); if (fromField.getValue() == null && toField.getValue() == null) { continue; } try { if ((fromField.getValue() == null && toField.getValue() != null) || (toField.getValue() == null && fromField.getValue() != null) || (!fromField.getValue().equals(toField.getValue()))) { // serialize data as JSON if field names are : preferences, addresses or merged_account_ids String fieldFromValue = null; String fieldToValue = null; if (fromField.getFieldName().equals("preferences")) { if (fromField.getValue() != null && toField.getValue() != null) { fieldFromValue = objectMapper.writer().writeValueAsString(objectDiff.getFrom().getPreferences()); fieldToValue = objectMapper.writer().writeValueAsString(objectDiff.getTo().getPreferences()); if (fieldFromValue.equals(fieldToValue)) { continue; } } else { fieldFromValue = fromField.getValue() == null ? "null" : objectMapper.writer().writeValueAsString(objectDiff.getFrom().getPreferences()); fieldToValue = toField.getValue() == null ? "null" : objectMapper.writer().writeValueAsString(objectDiff.getTo().getPreferences()); } } else if (fromField.getFieldName().equals("addresses")) { if (fromField.getValue() != null && toField.getValue() != null) { fieldFromValue = objectMapper.writer().writeValueAsString(objectDiff.getFrom().getAddresses()); fieldToValue = objectMapper.writer().writeValueAsString(objectDiff.getTo().getAddresses()); if (fieldFromValue.equals(fieldToValue)) { continue; } } else { fieldFromValue = fromField.getValue() == null ? "null" : objectMapper.writer().writeValueAsString(objectDiff.getFrom().getAddresses()); fieldToValue = toField.getValue() == null ? "null" : objectMapper.writer().writeValueAsString(objectDiff.getTo().getAddresses()); } } else if (fromField.getFieldName().equals("merged_account_ids")) { if (fromField.getValue() != null && toField.getValue() != null) { fieldFromValue = objectMapper.writer().writeValueAsString(objectDiff.getFrom().getMerged_account_ids()); fieldToValue = objectMapper.writer().writeValueAsString(objectDiff.getTo().getMerged_account_ids()); if (fieldFromValue.equals(fieldToValue)) { continue; } } else { fieldFromValue = fromField.getValue() == null ? "null" : objectMapper.writer().writeValueAsString(objectDiff.getFrom().getMerged_account_ids()); fieldToValue = toField.getValue() == null ? "null" : objectMapper.writer().writeValueAsString(objectDiff.getTo().getMerged_account_ids()); } } else { fieldFromValue = fromField.getValue() == null ? "null" : fromField.getValue().toString(); fieldToValue = toField.getValue() == null ? "null" : toField.getValue().toString(); } fieldChanges.add(new FieldChange(fromField.getFieldName(), fieldFromValue, fieldToValue)); } } catch (Exception e) { throw new SerializationFailedException("Error interpreting change from diff : " + e.getMessage(), e); } } personsList.add(new Person(Long.valueOf(!NumberUtils.isNumber(objectDiff.getFrom().getPrimary_phone()) ? "0" : objectDiff.getFrom().getPrimary_phone().trim()), objectDiff.getFrom().getFirst_name(), objectDiff.getFrom().getLast_name(),0L,"false",fieldChanges)); } return personsList; } }