Skip to content

Commit

Permalink
finish metadata support and JsonSerializer use metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
chaokunyang committed Aug 14, 2017
1 parent 647a01e commit 45d8acb
Show file tree
Hide file tree
Showing 16 changed files with 297 additions and 139 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* @author chaokunyang
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
@Target({ ElementType.METHOD, ElementType.FIELD })
@Documented
public @interface DocumentId {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* @author chaokunyang
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) // 后期基于ElementType.ANNOTATION_TYPE编写元注解
@Target({ ElementType.METHOD, ElementType.FIELD }) // in future, code meta annotation base on ElementType.ANNOTATION_TYPE
@Documented
@Inherited
public @interface Field {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* @author chaokunyang
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface InnerField {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
* @author chaokunyang
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface MultiFields {

Field mainField();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.timeyang.jkes.core.elasticsearch.exception;

/**
* @author chaokunyang
*/
public class IllegalJkesStateException extends IllegalStateException {

public IllegalJkesStateException() {
}

public IllegalJkesStateException(String s) {
super(s);
}

public IllegalJkesStateException(String message, Throwable cause) {
super(message, cause);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
import com.timeyang.jkes.core.annotation.InnerField;
import com.timeyang.jkes.core.annotation.MultiFields;
import com.timeyang.jkes.core.annotation.NotThreadSafe;
import com.timeyang.jkes.core.elasticsearch.exception.IllegalJkesStateException;
import com.timeyang.jkes.core.exception.FieldTypeInferException;
import com.timeyang.jkes.core.util.DocumentUtils;
import com.timeyang.jkes.core.metadata.DocumentMetadata;
import com.timeyang.jkes.core.metadata.FieldMetadata;
import com.timeyang.jkes.core.metadata.Metadata;
import com.timeyang.jkes.core.metadata.MultiFieldsMetadata;
import com.timeyang.jkes.core.util.ReflectionUtils;
import com.timeyang.jkes.core.util.StringUtils;
import org.json.JSONObject;
Expand Down Expand Up @@ -79,40 +83,26 @@ private JSONObject getEntityMappingProperties(Class<?> clazz) {
context.addLast(clazz);

JSONObject properties = new JSONObject();
Method[] methods = clazz.getMethods(); // include superclass methods
for(Method method : methods) {
Field fieldAnnotation = method.getAnnotation(Field.class);

if(fieldAnnotation == null) {
String methodName = method.getName();
if(methodName.startsWith("get") || methodName.startsWith("is")) {
String memberFieldName = ReflectionUtils.getFieldNameForGetter(methodName);
fieldAnnotation = ReflectionUtils.getFieldAnnotation(clazz, memberFieldName, Field.class);
}
}

if(fieldAnnotation != null && !willRecursive(method)) {

// all single field mapping is added here, getSingleFieldMapping method just generate the value
properties.put(DocumentUtils.getFieldName(method),
getSingleFieldMapping(method, fieldAnnotation));
}else {
MultiFields multiFields = method.getAnnotation(MultiFields.class);
if(multiFields == null) {
String methodName = method.getName();
if(methodName.startsWith("get") || methodName.startsWith("is")) {
String memberFieldName = ReflectionUtils.getFieldNameForGetter(methodName);
multiFields = ReflectionUtils.getFieldAnnotation(clazz, memberFieldName, MultiFields.class);
}
}
if(multiFields != null && !willRecursive(method)) {

// all multi fields mapping is added here, getMultiFieldsMapping method just generate the value
properties.put(DocumentUtils.getFieldName(method),
getMultiFieldsMapping(method, multiFields));
}
}
Metadata metadata = Metadata.getMetadata();
if(Metadata.getMetadata() == null)
throw new IllegalJkesStateException("Metadata doesn't be inited correctly, the init method doesn't get invoked");
DocumentMetadata documentMetadata = metadata.getMetadataMap().get(clazz);
Set<FieldMetadata> fieldMetadataSet = documentMetadata.getFieldMetadataSet();
Set<MultiFieldsMetadata> multiFieldsMetadataSet = documentMetadata.getMultiFieldsMetadataSet();

for(FieldMetadata fieldMetadata : fieldMetadataSet) {
Method method = fieldMetadata.getMethod();
if(!willRecursive(method))
properties.put(fieldMetadata.getFieldName(),
getSingleFieldMapping(method, fieldMetadata.getField()));
}

for (MultiFieldsMetadata multiFieldsMetadata : multiFieldsMetadataSet) {
Method method = multiFieldsMetadata.getMethod();
if(!willRecursive(method))
properties.put(multiFieldsMetadata.getFieldName(),
getMultiFieldsMapping(multiFieldsMetadata.getMethod(), multiFieldsMetadata.getMultiFields()));
}

context.removeLast();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.timeyang.jkes.core.elasticsearch.serialize;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonStreamContext;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.timeyang.jkes.core.elasticsearch.exception.IllegalJkesStateException;
import com.timeyang.jkes.core.exception.IllegalMemberAccessException;
import com.timeyang.jkes.core.exception.ReflectiveInvocationTargetException;
import com.timeyang.jkes.core.metadata.DocumentMetadata;
import com.timeyang.jkes.core.metadata.FieldMetadata;
import com.timeyang.jkes.core.metadata.Metadata;
import com.timeyang.jkes.core.metadata.MultiFieldsMetadata;
import com.timeyang.jkes.core.util.ReflectionUtils;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Set;

/**
* Entity capable of search, json serializer
*
* @author chaokunyang
*/
public class MetaableJkesJsonSerializer<T> extends StdSerializer<T> {

public MetaableJkesJsonSerializer() {
this(null);
}

private MetaableJkesJsonSerializer(Class<T> t) {
super(t);
}

@Override
public Class<T> handledType() {
return _handledType;
}

@Override
public void serialize(T value, JsonGenerator gen, SerializerProvider provider) throws IOException {

JsonStreamContext context = gen.getOutputContext();
gen.setCurrentValue(value); // must set manually, or else the result of context.getCurrentValue() will be null。this method will call context.setCurrentValue(value);

gen.writeStartObject(); // writeStartObject(value) will call setCurrentValue(value) well
Class<?> entityClass = value.getClass();

if(Metadata.getMetadata() == null)
throw new IllegalJkesStateException("Metadata doesn't be inited correctly, the init method doesn't get invoked");
DocumentMetadata documentMetadata = Metadata.getMetadata().getMetadataMap().get(entityClass);
Set<FieldMetadata> fieldMetadataSet = documentMetadata.getFieldMetadataSet();
Set<MultiFieldsMetadata> multiFieldsMetadataSet = documentMetadata.getMultiFieldsMetadataSet();

for(FieldMetadata fieldMetadata : fieldMetadataSet) {
Method method = fieldMetadata.getMethod();
// check whether serialization will be recursive
if (willRecursive(context, method)) {
gen.writeEndObject();
return;
}

serializeField(value, gen, method, fieldMetadata.getFieldName());
}

for(MultiFieldsMetadata multiFieldsMetadata : multiFieldsMetadataSet) {
Method method = multiFieldsMetadata.getMethod();
// check whether serialization will be recursive
if (willRecursive(context, method)) {
gen.writeEndObject();
return;
}

serializeField(value, gen, method, multiFieldsMetadata.getFieldName());
}

// gen.writeObjectField("extra_field", "whatever_value");
gen.writeEndObject();
}

private void serializeField(T value, JsonGenerator gen, Method method, String fieldName) throws IOException {
try {
Object v = method.invoke(value);

gen.writeObjectField(fieldName, v); // serialize data
} catch (IllegalAccessException e) {
throw new IllegalMemberAccessException(e);
} catch (InvocationTargetException e) {
throw new ReflectiveInvocationTargetException(e);
}
}

private boolean willRecursive(JsonStreamContext ctxt, Method method) throws IOException {
if (ctxt != null) {
JsonStreamContext ptxt;
ptxt = ctxt.getParent();
while(ptxt != null) {
if(ptxt.getCurrentValue() == null
|| !ReflectionUtils.getInnermostType(method).equals(ptxt.getCurrentValue().getClass().getCanonicalName())) {
ptxt = ptxt.getParent();
}else {
return true;
}
}
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.timeyang.jkes.core.annotation.Document;
import com.timeyang.jkes.core.elasticsearch.serialize.JkesJsonSerializer;
import com.timeyang.jkes.core.elasticsearch.serialize.MetaableJkesJsonSerializer;
import com.timeyang.jkes.core.util.ClassUtils;
import org.apache.kafka.common.errors.SerializationException;
import org.apache.kafka.common.serialization.Serializer;
Expand All @@ -26,7 +26,7 @@ public void configure(Map configs, boolean isKey) {

SimpleModule module = new SimpleModule();
Set<Class<?>> annotatedClasses = ClassUtils.getAnnotatedClasses(documentBasePackage, Document.class);
annotatedClasses.forEach(aClass -> module.addSerializer(aClass, new JkesJsonSerializer<>()));
annotatedClasses.forEach(aClass -> module.addSerializer(aClass, new MetaableJkesJsonSerializer<>()));

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.timeyang.jkes.core.support.Config;
import com.timeyang.jkes.core.util.DocumentUtils;
import com.timeyang.jkes.core.annotation.DocumentId;
import com.timeyang.jkes.core.elasticsearch.exception.IlllegalSearchStateException;
import com.timeyang.jkes.core.elasticsearch.exception.IllegalJkesStateException;
import com.timeyang.jkes.core.util.StringUtils;

import javax.persistence.Id;
Expand Down Expand Up @@ -72,7 +72,7 @@ public static String getKey(Object entity) {
Object key = method.invoke(entity);
return String.valueOf(key);
} catch (IllegalAccessException e) {
throw new IlllegalSearchStateException(
throw new IllegalJkesStateException(
DocumentId.class + " or " + Id.class + "can only be annotated on public class", e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
Expand All @@ -98,7 +98,7 @@ public static String getKey(Object entity) {
clazz = clazz.getSuperclass();
}while (clazz != null);

throw new IlllegalSearchStateException(domainClass + " doesn't have a document id. You either annotated a method with " + DocumentId.class + " , or annotated a field or getter method with " + Id.class);
throw new IllegalJkesStateException(domainClass + " doesn't have a document id. You either annotated a method with " + DocumentId.class + " , or annotated a field or getter method with " + Id.class);
}

public static String getDeleteTopic() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.timeyang.jkes.core.annotation.Immutable;
import lombok.Builder;

import java.util.Collections;
import java.util.Set;

/**
Expand Down Expand Up @@ -31,11 +32,34 @@ public DocumentMetadata(
VersionMetadata versionMetadata,
String topic) {
this.clazz = clazz;
this.fieldMetadataSet = fieldMetadataSet;
this.multiFieldsMetadataSet = multiFieldsMetadataSet;
this.fieldMetadataSet = Collections.unmodifiableSet(fieldMetadataSet);
this.multiFieldsMetadataSet = Collections.unmodifiableSet(multiFieldsMetadataSet);
this.idMetadata = idMetadata;
this.versionMetadata = versionMetadata;
this.topic = topic;
}

public Class<?> getClazz() {
return clazz;
}

public Set<FieldMetadata> getFieldMetadataSet() {
return fieldMetadataSet;
}

public Set<MultiFieldsMetadata> getMultiFieldsMetadataSet() {
return multiFieldsMetadataSet;
}

public IdMetadata getIdMetadata() {
return idMetadata;
}

public VersionMetadata getVersionMetadata() {
return versionMetadata;
}

public String getTopic() {
return topic;
}
}
Loading

0 comments on commit 45d8acb

Please sign in to comment.