
com.rest4j.impl.ConcreteClassMapping Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rest4j-core Show documentation
Show all versions of rest4j-core Show documentation
Framework for building RESTful services in Java
The newest version!
package com.rest4j.impl;
import com.rest4j.ApiException;
import com.rest4j.ConfigurationException;
import com.rest4j.DynamicMapper;
import com.rest4j.ServiceProvider;
import com.rest4j.impl.model.Field;
import com.rest4j.impl.model.FieldAccessType;
import com.rest4j.impl.model.Model;
import com.rest4j.json.JSONException;
import com.rest4j.json.JSONObject;
import com.rest4j.type.ObjectApiType;
import org.w3c.dom.Element;
import javax.annotation.Nullable;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
/**
* @author Joseph Kapizza
*/
public class ConcreteClassMapping implements ObjectApiType {
private final Model model;
private final MarshallerImpl marshaller;
String name;
Class clz;
FieldMapping[] fields;
List leftoverFields = new ArrayList();
Object customMapper;
ObjectApiTypeImpl objectApiType;
final static Logger log = Logger.getLogger(ConcreteClassMapping.class.getName());
public ConcreteClassMapping(MarshallerImpl marshaller, Class clz, Model model, Object customMapper, ServiceProvider serviceProvider, ObjectApiTypeImpl objectApiType) throws ConfigurationException {
this.marshaller = marshaller;
this.name = model.getName();
this.clz = clz;
this.customMapper = customMapper;
this.model = model;
this.objectApiType = objectApiType;
if (model.getFields() == null) {
this.fields = new FieldMapping[0];
return;
}
List fields = new ArrayList(model.getFields().getSimpleAndComplex().size());
for (Field fld : model.getFields().getSimpleAndComplex()) {
FieldMapping fieldMapping;
if (customMapper instanceof DynamicMapper) {
if (fld.getMappingMethod() != null) {
throw new ConfigurationException("mapping-method cannot be used along with DynamicMapper");
}
fieldMapping = new DynamicFieldMapping(marshaller, fld, (DynamicMapper)customMapper, name /* owner name */);
} else if (fld.getMappingMethod() == null) {
if (fld.getProp() != null && fld.getProp().contains(".")) {
fieldMapping = new NestedFieldMapping(marshaller, fld, name /* owner name */);
} else {
fieldMapping = new SimpleFieldMapping(marshaller, fld, name /* owner name */);
}
} else {
fieldMapping = new CustomFieldMapping(marshaller, fld, customMapper, name /* owner name */);
}
fieldMapping.setServiceProvider(serviceProvider);
if (!fieldMapping.initAccessors(clz)) {
log.warning("No accessors found for property "+fieldMapping.getName()+" of class "+clz.getName());
leftoverFields.add(fld);
continue;
}
fields.add(fieldMapping);
}
this.fields = fields.toArray(new FieldMapping[fields.size()]);
}
void unmarshal(JSONObject object, Object inst) throws ApiException {
// first unmarshal non-custom-mapping properties, so that we could use them in a custom mapping logic
for (FieldMapping field : getOrderedFieldsForUnmarshal()) {
Object fieldVal = object.opt(field.name);
fieldVal = objectApiType.fieldFilter.unmarshal(fieldVal, inst, objectApiType, field);
if (fieldVal == null && field.isOptional()) {
// absent fields are initialized to default values or null
continue;
}
fieldVal = field.unmarshal(fieldVal);
field.set(inst, fieldVal);
}
}
void marshal(JSONObject json, Object val) throws ApiException {
for (FieldMapping field : fields) {
if (field.access == FieldAccessType.WRITEONLY) continue;
Object fieldValue = field.value == null ? field.get(val) : field.value;
fieldValue = field.marshal(fieldValue);
fieldValue = objectApiType.fieldFilter.marshal(fieldValue, val, objectApiType, field);
if (fieldValue != null) {
try {
json.put(field.name, fieldValue);
} catch (JSONException e) {
throw new ApiException("Wrong value of field "+name+"."+field.name+": "+e.getMessage()).setHttpStatus(500);
}
}
}
}
void unmarshalPatch(JSONObject object, Object patched) throws ApiException {
for (FieldMapping field : getOrderedFieldsForUnmarshal()) {
if (object.has(field.name)) {
Object fieldVal = object.opt(field.name);
fieldVal = objectApiType.fieldFilter.unmarshal(fieldVal, patched, objectApiType, field);
fieldVal = field.unmarshalPatch(fieldVal, patched);
field.set(patched, fieldVal);
}
}
}
private ArrayList getOrderedFieldsForUnmarshal() {
// first unmarshal non-custom-mapping properties, so that we could use them in a custom mapping logic
ArrayList ordered = new ArrayList();
for (FieldMapping field : fields) {
if (field instanceof CustomFieldMapping || field.access == FieldAccessType.READONLY) continue;
ordered.add(field);
}
for (FieldMapping field : fields) {
if (!(field instanceof CustomFieldMapping) || field.access == FieldAccessType.READONLY) continue;
ordered.add(field);
}
return ordered;
}
void link() throws ConfigurationException {
for (int i = 0; i < fields.length; i++) {
FieldMapping fieldImpl = fields[i];
fieldImpl.link(marshaller);
}
}
@Override
public String getName() {
return name;
}
@Override
public List getFields() {
ArrayList list = new ArrayList();
for (FieldMapping mapping: fields) {
list.add(mapping);
}
return list;
}
@Override
public List getExtra() {
return objectApiType.getExtra();
}
@Override
public Class getJavaClass() {
return clz;
}
@Override
public ObjectApiType getSubtype(Class subclass) throws ApiException {
return objectApiType.getSubtype(subclass);
}
@Override
public boolean check(Type javaType) {
javaType = Util.getClass(javaType);
return javaType == clz;
}
@Override
public Object cast(@Nullable Object value, Type javaType) throws NullPointerException {
return value;
}
@Override
public String getJavaName() {
return clz.getName();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy