private void readColumn(Column columnAnn, DeployBeanProperty prop) {

    if (!isEmpty(columnAnn.name())) {
      String dbColumn = databasePlatform.convertQuotedIdentifiers(columnAnn.name());
      prop.setDbColumn(dbColumn);
    }

    prop.setDbInsertable(columnAnn.insertable());
    prop.setDbUpdateable(columnAnn.updatable());
    prop.setNullable(columnAnn.nullable());
    prop.setUnique(columnAnn.unique());
    if (columnAnn.precision() > 0) {
      prop.setDbLength(columnAnn.precision());
    } else if (columnAnn.length() != 255) {
      // set default 255 on DbTypeMap
      prop.setDbLength(columnAnn.length());
    }
    prop.setDbScale(columnAnn.scale());
    prop.setDbColumnDefn(columnAnn.columnDefinition());

    String baseTable = descriptor.getBaseTable();
    String tableName = columnAnn.table();
    if (tableName.equals("") || tableName.equalsIgnoreCase(baseTable)) {
      // its a base table property...
    } else {
      // its on a secondary table...
      prop.setSecondaryTable(tableName);
      // DeployTableJoin tableJoin = info.getTableJoin(tableName);
      // tableJoin.addProperty(prop);
    }
  }
  private void readId(Id id, DeployBeanProperty prop) {

    prop.setId(true);
    prop.setNullable(false);

    if (prop.getPropertyType().equals(UUID.class)) {
      // An Id of type UUID
      if (descriptor.getIdGeneratorName() == null) {
        // Without a generator explicitly specified
        // so will use the default one AUTO_UUID
        descriptor.setIdGeneratorName(UuidIdGenerator.AUTO_UUID);
        descriptor.setIdType(IdType.GENERATOR);
      }
    }
  }
  private void readTemporal(Temporal temporal, DeployBeanProperty prop) {

    TemporalType type = temporal.value();
    if (type.equals(TemporalType.DATE)) {
      prop.setDbType(Types.DATE);

    } else if (type.equals(TemporalType.TIMESTAMP)) {
      prop.setDbType(Types.TIMESTAMP);

    } else if (type.equals(TemporalType.TIME)) {
      prop.setDbType(Types.TIME);

    } else {
      throw new PersistenceException("Unhandled type " + type);
    }
  }
  private void readGenValue(GeneratedValue gen, DeployBeanProperty prop) {

    String genName = gen.generator();

    SequenceGenerator sequenceGenerator = find(prop, SequenceGenerator.class);
    if (sequenceGenerator != null) {
      if (sequenceGenerator.name().equals(genName)) {
        genName = sequenceGenerator.sequenceName();
      }
    }

    GenerationType strategy = gen.strategy();

    if (strategy == GenerationType.IDENTITY) {
      descriptor.setIdType(IdType.IDENTITY);

    } else if (strategy == GenerationType.SEQUENCE) {
      descriptor.setIdType(IdType.SEQUENCE);
      if (genName != null && genName.length() > 0) {
        descriptor.setIdGeneratorName(genName);
      }

    } else if (strategy == GenerationType.AUTO) {
      if (prop.getPropertyType().equals(UUID.class)) {
        descriptor.setIdGeneratorName(UuidIdGenerator.AUTO_UUID);
        descriptor.setIdType(IdType.GENERATOR);

      } else {
        // use DatabasePlatform defaults
      }
    }
  }
  private DataEncryptSupport createDataEncryptSupport(DeployBeanProperty prop) {

    String table = info.getDescriptor().getBaseTable();
    String column = prop.getDbColumn();

    return util.createDataEncryptSupport(table, column);
  }
  private DeployBeanProperty createProp(
      int level,
      DeployBeanDescriptor<?> desc,
      Field field,
      Class<?> beanType,
      Method getter,
      Method setter) {

    DeployBeanProperty prop = createProp(desc, field);
    if (prop == null) {
      // transient annotation on unsupported type
      return null;
    } else {
      prop.setOwningType(beanType);
      prop.setName(field.getName());

      // the getter or setter could be null if we are using
      // javaagent type enhancement. If we are using subclass
      // generation then we do need to find the getter and setter
      prop.setReadMethod(getter);
      prop.setWriteMethod(setter);
      prop.setField(field);
      return prop;
    }
  }
  private void setEncryption(DeployBeanProperty prop, boolean dbEncString, int dbLen) {

    util.checkEncryptKeyManagerDefined(prop.getFullBeanName());

    ScalarType<?> st = prop.getScalarType();
    if (byte[].class.equals(st.getType())) {
      // Always using Java client encryption rather than DB for encryption
      // of binary data (partially as this is not supported on all db's etc)
      // This could be reviewed at a later stage.
      ScalarTypeBytesBase baseType = (ScalarTypeBytesBase) st;
      DataEncryptSupport support = createDataEncryptSupport(prop);
      ScalarTypeBytesEncrypted encryptedScalarType =
          new ScalarTypeBytesEncrypted(baseType, support);
      prop.setScalarType(encryptedScalarType);
      prop.setLocalEncrypted(true);
      return;
    }
    if (dbEncString) {

      DbEncrypt dbEncrypt = util.getDbPlatform().getDbEncrypt();

      if (dbEncrypt != null) {
        // check if we have a DB encryption function for this type
        int jdbcType = prop.getScalarType().getJdbcType();
        DbEncryptFunction dbEncryptFunction = dbEncrypt.getDbEncryptFunction(jdbcType);
        if (dbEncryptFunction != null) {
          // Use DB functions to encrypt and decrypt
          prop.setDbEncryptFunction(dbEncryptFunction, dbEncrypt, dbLen);
          return;
        }
      }
    }

    prop.setScalarType(createScalarType(prop, st));
    prop.setLocalEncrypted(true);
    if (dbLen > 0) {
      prop.setDbLength(dbLen);
    }
  }
  /** Read the Id marker annotations on EmbeddedId properties. */
  private void readAssocOne(DeployBeanProperty prop) {

    Id id = get(prop, Id.class);
    if (id != null) {
      prop.setId(true);
      prop.setNullable(false);
    }

    EmbeddedId embeddedId = get(prop, EmbeddedId.class);
    if (embeddedId != null) {
      prop.setId(true);
      prop.setNullable(false);
      prop.setEmbedded(true);
    }

    if (prop instanceof DeployBeanPropertyAssocOne<?>) {
      if (prop.isId() && !prop.isEmbedded()) {
        prop.setEmbedded(true);
      }
      readEmbeddedAttributeOverrides((DeployBeanPropertyAssocOne<?>) prop);
    }
  }
  /** Create the appropriate properties for a bean. */
  public void createProperties(DeployBeanDescriptor<?> desc) {

    createProperties(desc, desc.getBeanType(), 0);
    desc.sortProperties();

    // check the transient properties...
    Iterator<DeployBeanProperty> it = desc.propertiesAll();

    while (it.hasNext()) {
      DeployBeanProperty prop = it.next();
      if (prop.isTransient()) {
        if (prop.getWriteMethod() == null || prop.getReadMethod() == null) {
          // Typically a helper method ... this is expected
          logger.finest("... transient: " + prop.getFullBeanName());
        } else {
          // dubious, possible error...
          String msg = Message.msg("deploy.property.nofield", desc.getFullName(), prop.getName());
          logger.warning(msg);
        }
      }
    }
  }
  private void readField(DeployBeanProperty prop) {

    // all Enums will have a ScalarType assigned...
    boolean isEnum = prop.getPropertyType().isEnum();
    Enumerated enumerated = get(prop, Enumerated.class);
    if (isEnum || enumerated != null) {
      util.setEnumScalarType(enumerated, prop);
    }

    // its persistent and assumed to be on the base table
    // rather than on a secondary table
    prop.setDbRead(true);
    prop.setDbInsertable(true);
    prop.setDbUpdateable(true);

    Column column = get(prop, Column.class);
    if (column != null) {
      readColumn(column, prop);
    }
    Expose expose = get(prop, Expose.class);
    if (expose != null) {
      prop.setExposeSerialize(expose.serialize());
      prop.setExposeDeserialize(expose.deserialize());
    }

    if (prop.getDbColumn() == null) {
      // No @Column annotation or @Column.name() not set
      // Use the NamingConvention to set the DB column name
      String dbColumn = namingConvention.getColumnFromProperty(beanType, prop.getName());
      prop.setDbColumn(dbColumn);
    }

    GeneratedValue gen = get(prop, GeneratedValue.class);
    if (gen != null) {
      readGenValue(gen, prop);
    }

    Id id = (Id) get(prop, Id.class);
    if (id != null) {
      readId(id, prop);
    }

    // determine the JDBC type using Lob/Temporal
    // otherwise based on the property Class
    Lob lob = get(prop, Lob.class);
    Temporal temporal = get(prop, Temporal.class);
    if (temporal != null) {
      readTemporal(temporal, prop);

    } else if (lob != null) {
      util.setLobType(prop);
    }

    Formula formula = get(prop, Formula.class);
    if (formula != null) {
      prop.setSqlFormula(formula.select(), formula.join());
    }

    Version version = get(prop, Version.class);
    if (version != null) {
      // explicitly specify a version column
      prop.setVersionColumn(true);
      generatedPropFactory.setVersion(prop);
    }

    Basic basic = get(prop, Basic.class);
    if (basic != null) {
      prop.setFetchType(basic.fetch());
      if (!basic.optional()) {
        prop.setNullable(false);
      }
    } else if (prop.isLob()) {
      // use the default Lob fetchType
      prop.setFetchType(defaultLobFetchType);
    }

    CreatedTimestamp ct = get(prop, CreatedTimestamp.class);
    if (ct != null) {
      generatedPropFactory.setInsertTimestamp(prop);
    }

    UpdatedTimestamp ut = get(prop, UpdatedTimestamp.class);
    if (ut != null) {
      generatedPropFactory.setUpdateTimestamp(prop);
    }

    if (validationAnnotations) {
      NotNull notNull = get(prop, NotNull.class);
      if (notNull != null && isNotNullOnAllValidationGroups(notNull.groups())) {
        // Not null on all validation groups so enable
        // DDL generation of Not Null Constraint
        prop.setNullable(false);
      }

      Size size = get(prop, Size.class);
      if (size != null) {
        if (size.max() < Integer.MAX_VALUE) {
          // explicitly specify a version column
          prop.setDbLength(size.max());
        }
      }
    }

    EmbeddedColumns columns = get(prop, EmbeddedColumns.class);
    if (columns != null) {
      if (prop instanceof DeployBeanPropertyCompound) {
        DeployBeanPropertyCompound p = (DeployBeanPropertyCompound) prop;

        // convert into a Map
        String propColumns = columns.columns();
        Map<String, String> propMap = StringHelper.delimitedToMap(propColumns, ",", "=");

        p.getDeployEmbedded().putAll(propMap);

        CtCompoundType<?> compoundType = p.getCompoundType();
        if (compoundType == null) {
          throw new RuntimeException("No registered CtCompoundType for " + p.getPropertyType());
        }

      } else {
        throw new RuntimeException(
            "Can't use EmbeddedColumns on ScalarType " + prop.getFullBeanName());
      }
    }

    // Want to process last so we can use with @Formula
    Transient t = get(prop, Transient.class);
    if (t != null) {
      // it is not a persistent property.
      prop.setDbRead(false);
      prop.setDbInsertable(false);
      prop.setDbUpdateable(false);
      prop.setTransient(true);
    }

    if (!prop.isTransient()) {

      EncryptDeploy encryptDeploy =
          util.getEncryptDeploy(info.getDescriptor().getBaseTableFull(), prop.getDbColumn());
      if (encryptDeploy == null || encryptDeploy.getMode().equals(Mode.MODE_ANNOTATION)) {
        Encrypted encrypted = get(prop, Encrypted.class);
        if (encrypted != null) {
          setEncryption(prop, encrypted.dbEncryption(), encrypted.dbLength());
        }
      } else if (Mode.MODE_ENCRYPT.equals(encryptDeploy.getMode())) {
        setEncryption(prop, encryptDeploy.isDbEncrypt(), encryptDeploy.getDbLength());
      }
    }

    Index index = get(prop, Index.class);
    if (index != null) {
      if (hasRelationshipItem(prop)) {
        throw new RuntimeException("Can't use Index on foreign key relationships.");
      }
      prop.setIndexed(true);
      prop.setIndexName(index.value());
    }
  }
 private ScalarTypeBytesBase getDbEncryptType(DeployBeanProperty prop) {
   int dbType = prop.isLob() ? Types.BLOB : Types.VARBINARY;
   return (ScalarTypeBytesBase) util.getTypeManager().getScalarType(dbType);
 }
  @SuppressWarnings({"unchecked", "rawtypes"})
  public DeployBeanPropertyLists(
      BeanDescriptorMap owner, BeanDescriptor<?> desc, DeployBeanDescriptor<?> deploy) {
    this.desc = desc;

    setImportedPrimaryKeys(deploy);

    DeployBeanPropertyAssocOne<?> deployUnidirectional = deploy.getUnidirectional();
    if (deployUnidirectional == null) {
      unidirectional = null;
    } else {
      unidirectional = new BeanPropertyAssocOne(owner, desc, deployUnidirectional);
    }

    this.propertyMap = new LinkedHashMap<String, BeanProperty>();

    // see if there is a discriminator property we should add
    String discriminatorColumn = null;
    BeanProperty discProperty = null;

    InheritInfo inheritInfo = deploy.getInheritInfo();
    if (inheritInfo != null) {
      // Create a BeanProperty for the discriminator column to support
      // using RawSql queries with inheritance
      discriminatorColumn = inheritInfo.getDiscriminatorColumn();
      DeployBeanProperty discDeployProp =
          new DeployBeanProperty(deploy, String.class, new ScalarTypeString(), null);
      discDeployProp.setDiscriminator();
      discDeployProp.setName(discriminatorColumn);
      discDeployProp.setDbColumn(discriminatorColumn);

      // only register it in the propertyMap. This might not be used if
      // an explicit property is mapped to the discriminator on the bean
      discProperty = new BeanProperty(desc, discDeployProp);
    }

    for (DeployBeanProperty prop : deploy.propertiesAll()) {
      if (discriminatorColumn != null && discriminatorColumn.equals(prop.getDbColumn())) {
        // we have an explicit property mapped to the discriminator column
        prop.setDiscriminator();
        discProperty = null;
      }
      BeanProperty beanProp = createBeanProperty(owner, prop);
      propertyMap.put(beanProp.getName(), beanProp);
    }

    int order = 0;
    for (BeanProperty prop : propertyMap.values()) {
      prop.setDeployOrder(order++);
      allocateToList(prop);
    }

    if (discProperty != null) {
      // put the discriminator property into the property map only
      // (after the real properties have been organised into their lists)
      propertyMap.put(discProperty.getName(), discProperty);
    }

    List<DeployTableJoin> deployTableJoins = deploy.getTableJoins();
    tableJoins = new TableJoin[deployTableJoins.size()];
    for (int i = 0; i < deployTableJoins.size(); i++) {
      tableJoins[i] = new TableJoin(deployTableJoins.get(i));
    }
  }
  /**
   * reflect the bean properties from Class. Some of these properties may not map to database
   * columns.
   */
  private void createProperties(DeployBeanDescriptor<?> desc, Class<?> beanType, int level) {

    boolean scalaObject = desc.isScalaObject();

    try {
      Method[] declaredMethods = beanType.getDeclaredMethods();
      Field[] fields = beanType.getDeclaredFields();

      for (int i = 0; i < fields.length; i++) {

        Field field = fields[i];
        if (Modifier.isStatic(field.getModifiers())) {
          // not interested in static fields

        } else if (Modifier.isTransient(field.getModifiers())) {
          // not interested in transient fields
          logger.finer("Skipping transient field " + field.getName() + " in " + beanType.getName());

        } else if (ignoreFieldByName(field.getName())) {
          // not interested this field (ebean or aspectJ field)

        } else {

          String fieldName = getFieldName(field, beanType);
          String initFieldName = initCap(fieldName);

          Method getter = findGetter(field, initFieldName, declaredMethods, scalaObject);
          Method setter = findSetter(field, initFieldName, declaredMethods, scalaObject);

          DeployBeanProperty prop = createProp(level, desc, field, beanType, getter, setter);
          if (prop == null) {
            // transient annotation on unsupported type

          } else {
            // set a order that gives priority to inherited properties
            // push Id/EmbeddedId up and CreatedTimestamp/UpdatedTimestamp down
            int sortOverride = prop.getSortOverride();
            prop.setSortOrder((level * 10000 + 100 - i + sortOverride));

            DeployBeanProperty replaced = desc.addBeanProperty(prop);
            if (replaced != null) {
              if (replaced.isTransient()) {
                // expected for inheritance...
              } else {
                String msg = "Huh??? property " + prop.getFullBeanName() + " being defined twice";
                msg += " but replaced property was not transient? This is not expected?";
                logger.warning(msg);
              }
            }
          }
        }
      }

      Class<?> superClass = beanType.getSuperclass();

      if (!superClass.equals(Object.class)) {
        // recursively add any properties in the inheritance heirarchy
        // up to the Object.class level...
        createProperties(desc, superClass, level + 1);
      }

    } catch (PersistenceException ex) {
      throw ex;

    } catch (Exception ex) {
      throw new PersistenceException(ex);
    }
  }
  public BeanProperty(BeanDescriptor<?> descriptor, DeployBeanProperty deploy) {

    this.descriptor = descriptor;
    this.name = InternString.intern(deploy.getName());
    this.propertyIndex = deploy.getPropertyIndex();
    this.unidirectionalShadow = deploy.isUndirectionalShadow();
    this.discriminator = deploy.isDiscriminator();
    this.localEncrypted = deploy.isLocalEncrypted();
    this.dbEncrypted = deploy.isDbEncrypted();
    this.dbEncryptedType = deploy.getDbEncryptedType();
    this.dbEncryptFunction = deploy.getDbEncryptFunction();
    this.dbBind = deploy.getDbBind();
    this.dbRead = deploy.isDbRead();
    this.dbInsertable = deploy.isDbInsertable();
    this.dbUpdatable = deploy.isDbUpdateable();
    this.excludedFromHistory = deploy.isExcludedFromHistory();
    this.draft = deploy.isDraft();
    this.draftDirty = deploy.isDraftDirty();
    this.draftOnly = deploy.isDraftOnly();
    this.draftReset = deploy.isDraftReset();
    this.secondaryTable = deploy.isSecondaryTable();
    if (secondaryTable) {
      this.secondaryTableJoin = new TableJoin(deploy.getSecondaryTableJoin());
      this.secondaryTableJoinPrefix = deploy.getSecondaryTableJoinPrefix();
    } else {
      this.secondaryTableJoin = null;
      this.secondaryTableJoinPrefix = null;
    }
    this.fetchEager = deploy.isFetchEager();
    this.isTransient = deploy.isTransient();
    this.nullable = deploy.isNullable();
    this.unique = deploy.isUnique();
    this.naturalKey = deploy.isNaturalKey();
    this.dbLength = deploy.getDbLength();
    this.dbScale = deploy.getDbScale();
    this.dbColumnDefn = InternString.intern(deploy.getDbColumnDefn());
    this.dbColumnDefault = deploy.getDbColumnDefault();

    this.inherited = false; // deploy.isInherited();
    this.owningType = deploy.getOwningType();
    this.local = deploy.isLocal();

    this.version = deploy.isVersionColumn();
    this.embedded = deploy.isEmbedded();
    this.id = deploy.isId();
    this.generatedProperty = deploy.getGeneratedProperty();
    this.getter = deploy.getGetter();
    this.setter = deploy.getSetter();

    this.dbColumn = tableAliasIntern(descriptor, deploy.getDbColumn(), false, null);
    this.dbComment = deploy.getDbComment();
    this.sqlFormulaJoin = InternString.intern(deploy.getSqlFormulaJoin());
    this.sqlFormulaSelect = InternString.intern(deploy.getSqlFormulaSelect());
    this.formula = sqlFormulaSelect != null;

    this.dbType = deploy.getDbType();
    this.scalarType = deploy.getScalarType();
    this.lob = isLobType(dbType);
    this.propertyType = deploy.getPropertyType();
    this.field = deploy.getField();
    this.docOptions = deploy.getDocPropertyOptions();

    this.elPlaceHolder = tableAliasIntern(descriptor, deploy.getElPlaceHolder(), false, null);
    this.elPlaceHolderEncrypted =
        tableAliasIntern(descriptor, deploy.getElPlaceHolder(), dbEncrypted, dbColumn);

    this.softDelete = deploy.isSoftDelete();
    if (softDelete) {
      ScalarTypeBoolean.BooleanBase boolType = (ScalarTypeBoolean.BooleanBase) scalarType;
      this.softDeleteDbSet = dbColumn + "=" + boolType.getDbTrueLiteral();
      this.softDeleteDbPredicate =
          "." + dbColumn + "," + boolType.getDbFalseLiteral() + ")=" + boolType.getDbFalseLiteral();
    } else {
      this.softDeleteDbSet = null;
      this.softDeleteDbPredicate = null;
    }

    this.jsonSerialize = deploy.isJsonSerialize();
    this.jsonDeserialize = deploy.isJsonDeserialize();
  }
示例#15
0
  /** Creates place holder objects that should never be called. */
  public static BeanReflectSetter create(DeployBeanProperty prop) {

    String fullName = prop.getFullBeanName();
    Method writeMethod = prop.getWriteMethod();
    return new RefCalled(fullName, writeMethod);
  }