All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.ebeaninternal.server.el.ElPropertyChain Maven / Gradle / Ivy

There is a newer version: 15.8.0
Show newest version
package io.ebeaninternal.server.el;

import io.ebean.bean.EntityBean;
import io.ebean.core.type.ScalarType;
import io.ebean.plugin.Property;
import io.ebean.text.StringParser;
import io.ebean.util.SplitName;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.deploy.BeanProperty;

import java.util.Arrays;


/**
 * A ElGetValue based on a chain of properties.
 * 

* Used to get the value for an compound expression like customer.name or * customer.shippingAddress.city etc. *

*

* Note that if any element in the chain returns null, then null is returned and * no further processing of the chain occurs. *

*/ public final class ElPropertyChain implements ElPropertyValue { private final String prefix; private final String placeHolder; private final String placeHolderEncrypted; private final String name; private final String expression; private final boolean containsMany; private final ElPropertyValue[] chain; private final boolean assocId; private final int last; private final BeanProperty lastBeanProperty; private final ScalarType scalarType; private final ElPropertyValue lastElPropertyValue; public ElPropertyChain(boolean containsMany, boolean embedded, String expression, ElPropertyValue[] chain) { this.containsMany = containsMany; this.chain = chain; this.expression = expression; int dotPos = expression.lastIndexOf('.'); if (dotPos > -1) { this.name = expression.substring(dotPos + 1); if (embedded) { int embPos = expression.lastIndexOf('.', dotPos - 1); this.prefix = embPos == -1 ? null : expression.substring(0, embPos); } else { this.prefix = expression.substring(0, dotPos); } } else { this.prefix = null; this.name = expression; } this.assocId = chain[chain.length - 1].isAssocId(); this.last = chain.length - 1; this.lastBeanProperty = chain[chain.length - 1].beanProperty(); if (lastBeanProperty != null) { this.scalarType = lastBeanProperty.scalarType(); } else { // case for nested compound type (non-scalar) this.scalarType = null; } this.lastElPropertyValue = chain[chain.length - 1]; this.placeHolder = placeHolder(prefix, lastElPropertyValue, false); this.placeHolderEncrypted = placeHolder(prefix, lastElPropertyValue, true); } @Override public String toString() { return "expr:" + expression + " chain:" + Arrays.toString(chain); } @Override public int fetchPreference() { return chain[0].fetchPreference(); } @Override public boolean isAggregation() { return false; } private String placeHolder(String prefix, ElPropertyValue lastElPropertyValue, boolean encrypted) { if (prefix == null) { return lastElPropertyValue.elPlaceholder(encrypted); } String el = lastElPropertyValue.elPlaceholder(encrypted); if (!el.contains("${}")) { // typically a secondary table property return el.replace("${", "${" + prefix + "."); } else { return el.replace(ROOT_ELPREFIX, "${" + prefix + "}"); } } /** * Return true if there is a many property from sinceProperty to * the end of this chain. */ @Override public boolean containsManySince(String sinceProperty) { if (sinceProperty == null) { return containsMany; } if (!expression.startsWith(sinceProperty)) { return containsMany; } int i = 1 + SplitName.count(sinceProperty); for (; i < chain.length; i++) { if (chain[i].beanProperty().containsMany()) { return true; } } return false; } @Override public boolean containsFormulaWithJoin() { return lastBeanProperty.containsFormulaWithJoin(); } @Override public boolean containsMany() { return containsMany; } @Override public String elPrefix() { return prefix; } @Override public String name() { return name; } @Override public String elName() { return expression; } @Override public String elPlaceholder(boolean encrypted) { return encrypted ? placeHolderEncrypted : placeHolder; } @Override public boolean isDbEncrypted() { return lastElPropertyValue.isDbEncrypted(); } @Override public boolean isLocalEncrypted() { return lastElPropertyValue.isLocalEncrypted(); } @Override public Object localEncrypt(Object value) { return lastElPropertyValue.localEncrypt(value); } @Override public String assocIsEmpty(SpiExpressionRequest request, String path) { return lastElPropertyValue.assocIsEmpty(request, path); } @Override public Object[] assocIdValues(EntityBean bean) { // Don't navigate the object graph as bean // is assumed to be the appropriate type return lastElPropertyValue.assocIdValues(bean); } @Override public String assocIdExpression(String prefix, String operator) { return lastElPropertyValue.assocIdExpression(expression, operator); } @Override public String assocIdInExpr(String prefix) { return lastElPropertyValue.assocIdInExpr(prefix); } @Override public String assocIdInValueExpr(boolean not, int size) { return lastElPropertyValue.assocIdInValueExpr(not, size); } @Override public boolean isAssocMany() { return lastElPropertyValue.isAssocMany(); } @Override public Property property() { return lastBeanProperty; } @Override public boolean isAssocId() { return assocId; } @Override public boolean isAssocProperty() { for (ElPropertyValue aChain : chain) { if (aChain.isAssocProperty()) { return true; } } return false; } @Override public String dbColumn() { return lastElPropertyValue.dbColumn(); } @Override public BeanProperty beanProperty() { return lastBeanProperty; } @Override public int jdbcType() { return scalarType == null ? 0 : scalarType.jdbcType(); } @Override public StringParser stringParser() { return scalarType; } @Override public Object convert(Object value) { // just convert using the last one in the chain return lastElPropertyValue.convert(value); } @Override public Object pathGet(Object bean) { for (ElPropertyValue aChain : chain) { if (aChain.isAssocMany()) { throw new UnsupportedOperationException("pathGet not supported on [" + expression + "], because " + aChain + " is an assocMany property"); } bean = aChain.pathGet(bean); if (bean == null) { return null; } } return bean; } @Override public Object pathGetNested(Object bean) { Object prevBean = bean; for (int i = 0; i < last; i++) { // always return non null prevBean prevBean = chain[i].pathGetNested(prevBean); } // try the last step in the chain return chain[last].pathGet(prevBean); } @Override public void pathSet(Object bean, Object value) { Object prevBean = bean; for (int i = 0; i < last; i++) { prevBean = chain[i].pathGetNested(prevBean); } if (prevBean != null) { if (lastBeanProperty != null) { // last chain element maps to a real scalar property lastBeanProperty.pathSet(prevBean, value); } else { // a non-scalar property of a Compound value object lastElPropertyValue.pathSet(prevBean, value); } } } @Override public String idNullOr(String filterManyExpression) { throw new UnsupportedOperationException(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy