
org.geomajas.internal.service.DtoConverterServiceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of geomajas-impl Show documentation
Show all versions of geomajas-impl Show documentation
Geomajas server: Main - Implementation
The newest version!
/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2016 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/
package org.geomajas.internal.service;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.geomajas.configuration.AbstractAttributeInfo;
import org.geomajas.configuration.AssociationAttributeInfo;
import org.geomajas.configuration.AssociationType;
import org.geomajas.configuration.AttributeInfo;
import org.geomajas.configuration.PrimitiveAttributeInfo;
import org.geomajas.geometry.Bbox;
import org.geomajas.geometry.Geometry;
import org.geomajas.geometry.conversion.jts.GeometryConverterService;
import org.geomajas.geometry.conversion.jts.JtsConversionException;
import org.geomajas.global.ExceptionCode;
import org.geomajas.global.GeomajasException;
import org.geomajas.internal.layer.feature.InternalFeatureImpl;
import org.geomajas.internal.layer.vector.lazy.LazyAttribute;
import org.geomajas.layer.LayerType;
import org.geomajas.layer.VectorLayerService;
import org.geomajas.layer.feature.Attribute;
import org.geomajas.layer.feature.Feature;
import org.geomajas.layer.feature.InternalFeature;
import org.geomajas.layer.feature.attribute.ArrayAttribute;
import org.geomajas.layer.feature.attribute.AssociationAttribute;
import org.geomajas.layer.feature.attribute.AssociationValue;
import org.geomajas.layer.feature.attribute.BooleanAttribute;
import org.geomajas.layer.feature.attribute.CurrencyAttribute;
import org.geomajas.layer.feature.attribute.DateAttribute;
import org.geomajas.layer.feature.attribute.DoubleAttribute;
import org.geomajas.layer.feature.attribute.FloatAttribute;
import org.geomajas.layer.feature.attribute.ImageUrlAttribute;
import org.geomajas.layer.feature.attribute.IntegerAttribute;
import org.geomajas.layer.feature.attribute.LongAttribute;
import org.geomajas.layer.feature.attribute.ManyToOneAttribute;
import org.geomajas.layer.feature.attribute.OneToManyAttribute;
import org.geomajas.layer.feature.attribute.PrimitiveAttribute;
import org.geomajas.layer.feature.attribute.ShortAttribute;
import org.geomajas.layer.feature.attribute.StringAttribute;
import org.geomajas.layer.feature.attribute.UrlAttribute;
import org.geomajas.layer.tile.InternalTile;
import org.geomajas.layer.tile.VectorTile;
import org.geomajas.service.DtoConverterService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
/**
* Default implementation of DTO converter.
*
* @author Jan De Moerloose
* @author Joachim Van der Auwera
* @author Pieter De Graef
*/
@Component()
public class DtoConverterServiceImpl implements DtoConverterService {
private ConvertUtilsBean cub = new ConvertUtilsBean();
// -------------------------------------------------------------------------
// Attribute conversion:
// -------------------------------------------------------------------------
/**
* Converts a DTO attribute into a generic attribute object.
*
* @param attribute
* The DTO attribute.
* @return The server side attribute representation. As we don't know at this point what kind of object the
* attribute is (that's a problem for the FeatureModel
), we return an Object
.
*/
public Object toInternal(Attribute> attribute) throws GeomajasException {
if (attribute instanceof PrimitiveAttribute>) {
return toPrimitiveObject((PrimitiveAttribute>) attribute);
} else if (attribute instanceof AssociationAttribute>) {
return toAssociationObject((AssociationAttribute>) attribute);
} else {
throw new GeomajasException(ExceptionCode.CONVERSION_PROBLEM, attribute);
}
}
@Override
public Attribute> toDto(Object object, AttributeInfo info) throws GeomajasException {
return toDto(object, (AbstractAttributeInfo) info);
}
@Override
public Attribute> toDto(Object object, AbstractAttributeInfo info) throws GeomajasException {
if (info instanceof PrimitiveAttributeInfo) {
if (object instanceof Object[]) {
return toArrayDto((Object[]) object, (PrimitiveAttributeInfo) info);
} else {
return toPrimitiveDto(object, (PrimitiveAttributeInfo) info);
}
} else if (info instanceof AssociationAttributeInfo) {
return toAssociationDto(object, (AssociationAttributeInfo) info);
} else {
throw new GeomajasException(ExceptionCode.CONVERSION_PROBLEM, info.getName());
}
}
// -------------------------------------------------------------------------
// Private methods - Attribute conversion:
// -------------------------------------------------------------------------
private Attribute> toAssociationDto(Object value, AssociationAttributeInfo associationAttributeInfo)
throws GeomajasException {
if (associationAttributeInfo.getType() == AssociationType.MANY_TO_ONE) {
return new ManyToOneAttribute(createAssociationValue(value, associationAttributeInfo));
} else if (associationAttributeInfo.getType() == AssociationType.ONE_TO_MANY) {
// Value should be an array of objects...
List associationValues = new ArrayList();
if (value != null && value instanceof Object[]) {
Object[] array = (Object[]) value;
for (Object bean : array) {
associationValues.add(createAssociationValue(bean, associationAttributeInfo));
}
}
return new OneToManyAttribute(associationValues);
}
return null;
}
private AssociationValue createAssociationValue(Object value, AssociationAttributeInfo associationAttributeInfo)
throws GeomajasException {
if (value == null) {
return null;
}
Map> attributes = new HashMap>();
boolean primitiveOnly = true;
for (AbstractAttributeInfo attributeInfo : associationAttributeInfo.getFeature().getAttributes()) {
Object propertyValue = getBeanProperty(value, attributeInfo.getName());
Attribute> attrib = toDto(propertyValue, attributeInfo);
attributes.put(attributeInfo.getName(), attrib);
if (!attrib.isPrimitive()) {
primitiveOnly = false;
}
}
PrimitiveAttribute> id = (PrimitiveAttribute>) toDto(
getBeanProperty(value, associationAttributeInfo.getFeature().getIdentifier().getName()),
associationAttributeInfo.getFeature().getIdentifier());
return new AssociationValue(id, attributes, primitiveOnly);
}
private Object getBeanProperty(Object bean, String property) throws GeomajasException {
PropertyDescriptor d = BeanUtils.getPropertyDescriptor(bean.getClass(), property);
if (d != null) {
Method m = d.getReadMethod();
if (m != null) {
if (!Modifier.isPublic(m.getDeclaringClass().getModifiers())) {
m.setAccessible(true);
}
Object value;
try {
value = m.invoke(bean);
} catch (Exception e) { // NOSONAR
throw new GeomajasException(e);
}
return value;
}
}
return null;
}
private Attribute> toPrimitiveDto(Object value, PrimitiveAttributeInfo info) {
switch (info.getType()) {
case BOOLEAN:
return new BooleanAttribute((Boolean) convertToClass(value, Boolean.class));
case SHORT:
return new ShortAttribute((Short) convertToClass(value, Short.class));
case INTEGER:
return new IntegerAttribute((Integer) convertToClass(value, Integer.class));
case LONG:
return new LongAttribute((Long) convertToClass(value, Long.class));
case FLOAT:
return new FloatAttribute((Float) convertToClass(value, Float.class));
case DOUBLE:
return new DoubleAttribute((Double) convertToClass(value, Double.class));
case CURRENCY:
return new CurrencyAttribute((String) convertToClass(value, String.class));
case STRING:
return new StringAttribute(value == null ? null : value.toString());
case DATE:
return new DateAttribute((Date) value);
case URL:
return new UrlAttribute((String) value);
case IMGURL:
return new ImageUrlAttribute((String) value);
default:
throw new IllegalArgumentException("Cannot create primitive attribute of type " + info);
}
}
private ArrayAttribute> toArrayDto(Object[] value, PrimitiveAttributeInfo info) {
switch (info.getType()) {
case BOOLEAN:
Boolean[] booleans = new Boolean[value.length];
for (int i = 0; i < value.length; i++) {
booleans[i] = (Boolean) convertToClass(value[i], Boolean.class);
}
return new ArrayAttribute(booleans);
case SHORT:
Short[] shorts = new Short[value.length];
for (int i = 0; i < value.length; i++) {
shorts[i] = (Short) convertToClass(value[i], Short.class);
}
return new ArrayAttribute(shorts);
case INTEGER:
Integer[] ints = new Integer[value.length];
for (int i = 0; i < value.length; i++) {
ints[i] = (Integer) convertToClass(value[i], Integer.class);
}
return new ArrayAttribute(ints);
case LONG:
Long[] longs = new Long[value.length];
for (int i = 0; i < value.length; i++) {
longs[i] = (Long) convertToClass(value[i], Long.class);
}
return new ArrayAttribute(longs);
case FLOAT:
Float[] floats = new Float[value.length];
for (int i = 0; i < value.length; i++) {
floats[i] = (Float) convertToClass(value[i], Float.class);
}
return new ArrayAttribute(floats);
case DOUBLE:
Double[] doubles = new Double[value.length];
for (int i = 0; i < value.length; i++) {
doubles[i] = (Double) convertToClass(value[i], Double.class);
}
return new ArrayAttribute(doubles);
case CURRENCY:
String[] values = new String[value.length];
for (int i = 0; i < value.length; i++) {
values[i] = (String) convertToClass(value[i], String.class);
}
return new ArrayAttribute(values);
case STRING:
String[] strings = new String[value.length];
for (int i = 0; i < value.length; i++) {
strings[i] = (value[i] == null ? null : value[i].toString());
}
return new ArrayAttribute(strings);
case DATE:
Date[] dates = new Date[value.length];
for (int i = 0; i < value.length; i++) {
dates[i] = (Date) convertToClass(value[i], Date.class);
}
return new ArrayAttribute(dates);
case URL:
String[] urls = new String[value.length];
for (int i = 0; i < value.length; i++) {
urls[i] = (value[i] == null ? null : value[i].toString());
}
return new ArrayAttribute(urls);
case IMGURL:
String[] images = new String[value.length];
for (int i = 0; i < value.length; i++) {
images[i] = (value[i] == null ? null : value[i].toString());
}
return new ArrayAttribute(images);
}
throw new IllegalArgumentException("Cannot create primitive attribute of type " + info);
}
private Object toAssociationObject(AssociationAttribute> primitiveAttribute) {
// TODO: implement
throw new UnsupportedOperationException("toAssociationObject() not implemented");
}
private Object toPrimitiveObject(PrimitiveAttribute> primitive) {
return primitive.getValue();
}
private Object convertToClass(Object object, Class> c) {
if (object == null) {
return null;
} else if (c.isInstance(object)) {
return object;
}
return cub.convert(object.toString(), c);
}
// -------------------------------------------------------------------------
// Feature conversion:
// -------------------------------------------------------------------------
/**
* Convert the server side feature to a DTO feature that can be sent to the client.
*
* @param feature
* The server-side feature representation.
* @param featureIncludes
* Indicate which aspects of the should be included see {@link VectorLayerService}
* @return Returns the DTO feature.
*/
public Feature toDto(InternalFeature feature, int featureIncludes) throws GeomajasException {
if (feature == null) {
return null;
}
Feature dto = new Feature(feature.getId());
if ((featureIncludes & VectorLayerService.FEATURE_INCLUDE_ATTRIBUTES) != 0 && null != feature.getAttributes()) {
// need to assure lazy attributes are converted to non-lazy attributes
Map attributes = new HashMap();
for (Map.Entry entry : feature.getAttributes().entrySet()) {
Attribute value = entry.getValue();
if (value instanceof LazyAttribute) {
value = ((LazyAttribute) value).instantiate();
}
attributes.put(entry.getKey(), value);
}
dto.setAttributes(attributes);
}
if ((featureIncludes & VectorLayerService.FEATURE_INCLUDE_LABEL) != 0) {
dto.setLabel(feature.getLabel());
}
if ((featureIncludes & VectorLayerService.FEATURE_INCLUDE_GEOMETRY) != 0) {
dto.setGeometry(toDto(feature.getGeometry()));
}
if ((featureIncludes & VectorLayerService.FEATURE_INCLUDE_STYLE) != 0 && null != feature.getStyleInfo()) {
dto.setStyleId(feature.getStyleInfo().getStyleId());
}
InternalFeatureImpl vFeature = (InternalFeatureImpl) feature;
dto.setClipped(vFeature.isClipped());
dto.setUpdatable(feature.isEditable());
dto.setDeletable(feature.isDeletable());
return dto;
}
@Override
public Feature toDto(InternalFeature feature) throws GeomajasException {
return toDto(feature, VectorLayerService.FEATURE_INCLUDE_ALL);
}
@Override
public InternalFeature toInternal(Feature dto) throws GeomajasException {
if (dto == null) {
return null;
}
InternalFeatureImpl feature = new InternalFeatureImpl();
feature.setAttributes(dto.getAttributes());
feature.setId(dto.getId());
feature.setLabel(dto.getLabel());
feature.setGeometry(toInternal(dto.getGeometry()));
feature.setClipped(dto.isClipped());
feature.setEditable(dto.isUpdatable());
feature.setDeletable(dto.isDeletable());
return feature;
}
// -------------------------------------------------------------------------
// Geometry conversion:
// -------------------------------------------------------------------------
@Override
public Geometry toDto(com.vividsolutions.jts.geom.Geometry geometry) throws GeomajasException {
if (geometry == null) {
return null;
}
try {
return GeometryConverterService.fromJts(geometry);
} catch (JtsConversionException jce) {
throw new GeomajasException(jce, ExceptionCode.CANNOT_CONVERT_GEOMETRY, geometry.getClass().getName());
}
}
@Override
public com.vividsolutions.jts.geom.Geometry toInternal(Geometry geometry) throws GeomajasException {
if (geometry == null) {
return null;
}
try {
return GeometryConverterService.toJts(geometry);
} catch (JtsConversionException jce) {
throw new GeomajasException(jce, ExceptionCode.CANNOT_CONVERT_GEOMETRY, geometry.getGeometryType());
}
}
// -------------------------------------------------------------------------
// Tile conversion:
// -------------------------------------------------------------------------
/**
* Convert a server-side tile representations into a DTO tile.
*
* @param tile
* The server-side representation of a tile.
* @param crs
* crs to include in features (if any)
* @param featureIncludes
* Indicate which aspects of the should be included see {@link org.geomajas.layer.VectorLayerService}
* @return Returns the DTO version that can be sent to the client.
*/
public VectorTile toDto(InternalTile tile, String crs, int featureIncludes) throws GeomajasException {
return toDto(tile);
}
/**
* Convert a server-side tile representations into a DTO tile.
*
* @param tile
* The server-side representation of a tile.
* @return Returns the DTO version that can be sent to the client.
*/
public VectorTile toDto(InternalTile tile) throws GeomajasException {
if (null != tile) {
VectorTile dto = new VectorTile();
dto.setClipped(tile.isClipped());
dto.setCode(tile.getCode());
dto.setCodes(tile.getCodes());
dto.setScreenHeight(tile.getScreenHeight());
dto.setScreenWidth(tile.getScreenWidth());
dto.setFeatureContent(tile.getFeatureContent());
dto.setLabelContent(tile.getLabelContent());
dto.setContentType(tile.getContentType());
return dto;
}
return null;
}
// -------------------------------------------------------------------------
// Bounding box conversion:
// -------------------------------------------------------------------------
/**
* Convert a {@link Bbox} to a JTS envelope.
*
* @param bbox bounding box
* @return JTS envelope
*/
public Envelope toInternal(Bbox bbox) {
return new Envelope(bbox.getX(), bbox.getMaxX(), bbox.getY(), bbox.getMaxY());
}
/**
* Convert JTS envelope into a {@link Bbox}.
*
* @param envelope
* JTS envelope
* @return Geomajas {@link Bbox}
*/
public Bbox toDto(Envelope envelope) {
return new Bbox(envelope.getMinX(), envelope.getMinY(), envelope.getWidth(), envelope.getHeight());
}
/**
* Convert a layer type to a geometry class.
*
* @param layerType
* layer type
* @return JTS class
*/
public Class extends com.vividsolutions.jts.geom.Geometry> toInternal(LayerType layerType) {
switch (layerType) {
case GEOMETRY:
return com.vividsolutions.jts.geom.Geometry.class;
case LINESTRING:
return LineString.class;
case MULTILINESTRING:
return MultiLineString.class;
case POINT:
return Point.class;
case MULTIPOINT:
return MultiPoint.class;
case POLYGON:
return Polygon.class;
case MULTIPOLYGON:
return MultiPolygon.class;
case RASTER:
return null;
default:
throw new IllegalStateException("Don't know how to handle layer type " + layerType);
}
}
/**
* Convert a geometry class to a layer type.
*
* @param geometryClass
* JTS geometry class
* @return Geomajas layer type
*/
public LayerType toDto(Class extends com.vividsolutions.jts.geom.Geometry> geometryClass) {
if (geometryClass == LineString.class) {
return LayerType.LINESTRING;
} else if (geometryClass == MultiLineString.class) {
return LayerType.MULTILINESTRING;
} else if (geometryClass == Point.class) {
return LayerType.POINT;
} else if (geometryClass == MultiPoint.class) {
return LayerType.MULTIPOINT;
} else if (geometryClass == Polygon.class) {
return LayerType.POLYGON;
} else if (geometryClass == MultiPolygon.class) {
return LayerType.MULTIPOLYGON;
} else {
return LayerType.GEOMETRY;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy