001package io.ebeaninternal.server.dto;
002
003import io.ebean.ProfileLocation;
004import io.ebean.metric.MetricFactory;
005import io.ebean.metric.QueryPlanMetric;
006import io.ebeaninternal.api.SpiDtoQuery;
007
008/**
009 * Request to map a resultSet columns for a query into a DTO bean.
010 */
011public class DtoMappingRequest {
012
013  private final Class type;
014
015  private final String label;
016
017  private final ProfileLocation profileLocation;
018
019  private final String sql;
020
021  private final boolean relaxedMode;
022
023  private final DtoColumn[] columnMeta;
024
025  public DtoMappingRequest(SpiDtoQuery query, String sql, DtoColumn[] columnMeta) {
026    this.type = query.getType();
027    this.label = query.getPlanLabel();
028    this.profileLocation = query.getProfileLocation();
029    this.sql = sql;
030    this.relaxedMode = query.isRelaxedMode();
031    this.columnMeta = columnMeta;
032  }
033
034  public DtoColumn[] getColumnMeta() {
035    return columnMeta;
036  }
037
038  public boolean isRelaxedMode() {
039    return relaxedMode;
040  }
041
042  public String getLabel() {
043    return label;
044  }
045
046  public String getSql() {
047    return sql;
048  }
049
050  public QueryPlanMetric createMetric() {
051    return MetricFactory.get().createQueryPlanMetric(type, label, profileLocation, sql);
052  }
053
054  /**
055   * Map all DB columns to setters.
056   */
057  DtoReadSet[] mapSetters(DtoMeta meta) {
058    DtoReadSet[] setterProps = new DtoReadSet[columnMeta.length];
059    for (int i = 0; i < columnMeta.length; i++) {
060      setterProps[i] = mapColumn(i, meta);
061    }
062    return setterProps;
063  }
064
065  /**
066   * Map DB columns after constructor to setters.
067   */
068  DtoReadSet[] mapArgPlusSetters(DtoMeta meta, int firstOnes) {
069    DtoReadSet[] setterProps = new DtoReadSet[columnMeta.length - firstOnes];
070    int pos = 0;
071    for (int i = firstOnes; i < columnMeta.length; i++) {
072      setterProps[pos++] = mapColumn(i, meta);
073    }
074    return setterProps;
075  }
076
077  private DtoReadSet mapColumn(int pos, DtoMeta meta) {
078    String label = columnMeta[pos].getLabel();
079    DtoReadSet property = meta.findProperty(label);
080    if (property == null || property.isReadOnly()) {
081      if (isRelaxedMode()) {
082        property = DtoReadSetColumnSkip.INSTANCE;
083      } else {
084        throw new IllegalStateException(unableToMapColumnMessage(columnMeta[pos], meta));
085      }
086    }
087    return property;
088  }
089
090  private String unableToMapColumnMessage(DtoColumn col, DtoMeta meta) {
091    return "Unable to map DB column " + col + " to a property with a setter method on " + meta.dtoType()+". Consider query.setRelaxedMode() to skip mapping this column.";
092  }
093
094}