/** * Copyright 2014 Sunny Gleason and 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 io.kazuki.v0.internal.v2schema.compact; import io.kazuki.v0.internal.v2schema.types.TypeTransforms; import io.kazuki.v0.store.schema.model.Attribute; import io.kazuki.v0.store.schema.model.Schema; import io.kazuki.v0.store.schema.model.Transform; import io.kazuki.v0.store.schema.model.TransformException; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; /** * Type-based compaction for object instances. For example, boolean compacts to char, datetime * compacts to long, enum compacts to int. This results in more marshalling more compact values. */ public class FieldTransform implements Transform<Map<String, Object>, Map<String, Object>> { private final Schema schema; private final Map<String, Transform<?, ?>> fieldCompactions; public FieldTransform(Schema schema) { if (schema == null) { throw new IllegalArgumentException("schema definition must not be null"); } this.schema = schema; Map<String, Transform<?, ?>> newFieldCompactions = new LinkedHashMap<String, Transform<?, ?>>(); for (Attribute attribute : schema.getAttributes()) { newFieldCompactions.put(attribute.getName(), TypeTransforms.validatorFor(attribute)); } this.fieldCompactions = Collections.unmodifiableMap(newFieldCompactions); } @Override public Map<String, Object> pack(Map<String, Object> instance) throws TransformException { if (instance == null) { throw new TransformException("instance must not be null"); } Map<String, Object> mindlessClone = new LinkedHashMap<String, Object>(); for (Map.Entry<String, Transform<?, ?>> e : fieldCompactions.entrySet()) { String attrName = e.getKey(); Transform validator = e.getValue(); Attribute attribute = schema.getAttribute(attrName); Object inbound = instance.get(attrName); if (inbound == null) { if (attribute.isNullable()) { mindlessClone.put(attrName, null); continue; } throw new TransformException("attribute must not be null: " + attrName); } try { Object transformed = validator.pack(inbound); mindlessClone.put(attrName, transformed); } catch (ClassCastException ex) { throw new TransformException("invalid attribute value for '" + attrName + "'"); } } Map<String, Object> mindlessCloneInOrder = new LinkedHashMap<String, Object>(); for (Map.Entry<String, Object> e : instance.entrySet()) { String attrName = e.getKey(); if (mindlessClone.containsKey(attrName)) { mindlessCloneInOrder.put(attrName, mindlessClone.get(attrName)); } else { mindlessCloneInOrder.put(attrName, instance.get(attrName)); } } return mindlessCloneInOrder; } @Override public Map<String, Object> unpack(Map<String, Object> instance) throws TransformException { if (instance == null) { throw new TransformException("instance must not be null"); } Map<String, Object> mindlessClone = new LinkedHashMap<String, Object>(); for (Map.Entry<String, Object> e : instance.entrySet()) { String attrName = e.getKey(); Attribute attribute = schema.getAttribute(attrName); if (attribute == null) { mindlessClone.put(attrName, e.getValue()); continue; } Object inbound = e.getValue(); if (inbound == null) { if (attribute.isNullable()) { mindlessClone.put(attrName, null); continue; } throw new TransformException("attribute must not be null: " + attrName); } Transform validator = fieldCompactions.get(attrName); Object untransformed = validator.unpack(inbound); mindlessClone.put(attrName, untransformed); } return mindlessClone; } public Object transformValue(String attrName, Object value) throws TransformException { try { Transform validator = (Transform) fieldCompactions.get(attrName); return validator != null ? validator.pack(value) : value; } catch (ClassCastException e) { throw new TransformException("invalid attribute value for '" + attrName + "': " + value.toString()); } } }