Пример #1
0
 /**
  * Convenience logging method to output the mapping information for an element, key, value field
  *
  * @param mapping The mapping
  */
 protected void debugMapping(JavaTypeMapping mapping) {
   if (NucleusLogger.DATASTORE.isDebugEnabled()) {
     // Provide field->column mapping debug message
     StringBuffer columnsStr = new StringBuffer();
     for (int i = 0; i < mapping.getNumberOfDatastoreMappings(); i++) {
       if (i > 0) {
         columnsStr.append(",");
       }
       columnsStr.append(mapping.getDatastoreMapping(i).getDatastoreField());
     }
     if (mapping.getNumberOfDatastoreMappings() == 0) {
       columnsStr.append("[none]");
     }
     StringBuffer datastoreMappingTypes = new StringBuffer();
     for (int i = 0; i < mapping.getNumberOfDatastoreMappings(); i++) {
       if (i > 0) {
         datastoreMappingTypes.append(',');
       }
       datastoreMappingTypes.append(mapping.getDatastoreMapping(i).getClass().getName());
     }
     NucleusLogger.DATASTORE.debug(
         LOCALISER.msg(
             "057010",
             mmd.getFullFieldName(),
             columnsStr.toString(),
             mapping.getClass().getName(),
             datastoreMappingTypes.toString()));
   }
 }
Пример #2
0
  /**
   * Accessor for the candidate keys for this table.
   *
   * @return The indices
   */
  protected List getExpectedCandidateKeys() {
    // The indices required by foreign keys (BaseTable)
    List candidateKeys = super.getExpectedCandidateKeys();

    if (keyMapping instanceof EmbeddedKeyPCMapping) {
      // Add all candidate keys required by fields of the embedded key
      EmbeddedKeyPCMapping embMapping = (EmbeddedKeyPCMapping) keyMapping;
      for (int i = 0; i < embMapping.getNumberOfJavaTypeMappings(); i++) {
        JavaTypeMapping embFieldMapping = embMapping.getJavaTypeMapping(i);
        UniqueMetaData umd = embFieldMapping.getMemberMetaData().getUniqueMetaData();
        if (umd != null) {
          CandidateKey ck = TableUtils.getCandidateKeyForField(this, umd, embFieldMapping);
          if (ck != null) {
            candidateKeys.add(ck);
          }
        }
      }
    }

    if (valueMapping instanceof EmbeddedValuePCMapping) {
      // Add all candidate keys required by fields of the embedded value
      EmbeddedValuePCMapping embMapping = (EmbeddedValuePCMapping) valueMapping;
      for (int i = 0; i < embMapping.getNumberOfJavaTypeMappings(); i++) {
        JavaTypeMapping embFieldMapping = embMapping.getJavaTypeMapping(i);
        UniqueMetaData umd = embFieldMapping.getMemberMetaData().getUniqueMetaData();
        if (umd != null) {
          CandidateKey ck = TableUtils.getCandidateKeyForField(this, umd, embFieldMapping);
          if (ck != null) {
            candidateKeys.add(ck);
          }
        }
      }
    }

    return candidateKeys;
  }
Пример #3
0
  /**
   * Accessor for the indices for this table. This includes both the user-defined indices (via
   * MetaData), and the ones required by foreign keys (required by relationships).
   *
   * @param clr The ClassLoaderResolver
   * @return The indices
   */
  protected Set getExpectedIndices(ClassLoaderResolver clr) {
    // The indices required by foreign keys (BaseTable)
    Set indices = super.getExpectedIndices(clr);

    if (keyMapping instanceof EmbeddedKeyPCMapping) {
      // Add all indices required by fields of the embedded key
      EmbeddedKeyPCMapping embMapping = (EmbeddedKeyPCMapping) keyMapping;
      for (int i = 0; i < embMapping.getNumberOfJavaTypeMappings(); i++) {
        JavaTypeMapping embFieldMapping = embMapping.getJavaTypeMapping(i);
        IndexMetaData imd = embFieldMapping.getMemberMetaData().getIndexMetaData();
        if (imd != null) {
          Index index = TableUtils.getIndexForField(this, imd, embFieldMapping);
          if (index != null) {
            indices.add(index);
          }
        }
      }
    }

    if (valueMapping instanceof EmbeddedValuePCMapping) {
      // Add all indices required by fields of the embedded value
      EmbeddedValuePCMapping embMapping = (EmbeddedValuePCMapping) valueMapping;
      for (int i = 0; i < embMapping.getNumberOfJavaTypeMappings(); i++) {
        JavaTypeMapping embFieldMapping = embMapping.getJavaTypeMapping(i);
        IndexMetaData imd = embFieldMapping.getMemberMetaData().getIndexMetaData();
        if (imd != null) {
          Index index = TableUtils.getIndexForField(this, imd, embFieldMapping);
          if (index != null) {
            indices.add(index);
          }
        }
      }
    }

    return indices;
  }
Пример #4
0
  /**
   * Convenience method to apply the user specification of <primary-key> columns
   *
   * @param pkmd MetaData for the primary key
   */
  protected void applyUserPrimaryKeySpecification(PrimaryKeyMetaData pkmd) {
    ColumnMetaData[] pkCols = pkmd.getColumnMetaData();
    for (int i = 0; i < pkCols.length; i++) {
      String colName = pkCols[i].getName();
      boolean found = false;
      for (int j = 0; j < ownerMapping.getNumberOfDatastoreMappings(); j++) {
        if (ownerMapping
            .getDatastoreMapping(j)
            .getDatastoreField()
            .getIdentifier()
            .getIdentifierName()
            .equals(colName)) {
          ownerMapping.getDatastoreMapping(j).getDatastoreField().setAsPrimaryKey();
          found = true;
        }
      }

      if (!found) {
        for (int j = 0; j < keyMapping.getNumberOfDatastoreMappings(); j++) {
          if (keyMapping
              .getDatastoreMapping(j)
              .getDatastoreField()
              .getIdentifier()
              .getIdentifierName()
              .equals(colName)) {
            keyMapping.getDatastoreMapping(j).getDatastoreField().setAsPrimaryKey();
            found = true;
          }
        }
      }

      if (!found) {
        for (int j = 0; j < valueMapping.getNumberOfDatastoreMappings(); j++) {
          if (valueMapping
              .getDatastoreMapping(j)
              .getDatastoreField()
              .getIdentifier()
              .getIdentifierName()
              .equals(colName)) {
            valueMapping.getDatastoreMapping(j).getDatastoreField().setAsPrimaryKey();
            found = true;
          }
        }
      }

      if (!found) {
        throw new NucleusUserException(LOCALISER.msg("057040", toString(), colName));
      }
    }
  }
Пример #5
0
  /**
   * Accessor for the expected foreign keys for this table.
   *
   * @param clr The ClassLoaderResolver
   * @return The expected foreign keys.
   */
  public List getExpectedForeignKeys(ClassLoaderResolver clr) {
    assertIsInitialized();

    boolean autoMode = false;
    if (storeMgr
        .getStringProperty("datanucleus.rdbms.constraintCreateMode")
        .equals("DataNucleus")) {
      autoMode = true;
    }

    ArrayList foreignKeys = new ArrayList();
    try {
      // FK from join table to owner table
      DatastoreClass referencedTable = storeMgr.getDatastoreClass(ownerType, clr);
      if (referencedTable != null) {
        // Take <foreign-key> from <join>
        ForeignKeyMetaData fkmd = null;
        if (mmd.getJoinMetaData() != null) {
          fkmd = mmd.getJoinMetaData().getForeignKeyMetaData();
        }
        if (fkmd != null || autoMode) {
          ForeignKey fk = new ForeignKey(ownerMapping, dba, referencedTable, true);
          fk.setForMetaData(fkmd);
          foreignKeys.add(fk);
        }
      }

      if (!isSerialisedValuePC()) {
        if (isEmbeddedValuePC()) {
          // Add any FKs for the fields of the (embedded) value
          EmbeddedValuePCMapping embMapping = (EmbeddedValuePCMapping) valueMapping;
          for (int i = 0; i < embMapping.getNumberOfJavaTypeMappings(); i++) {
            JavaTypeMapping embFieldMapping = embMapping.getJavaTypeMapping(i);
            AbstractMemberMetaData embFmd = embFieldMapping.getMemberMetaData();
            if (ClassUtils.isReferenceType(embFmd.getType())
                && embFieldMapping instanceof ReferenceMapping) {
              // Field is a reference type, so add a FK to the table of the PC for each PC
              // implementation
              Collection fks =
                  TableUtils.getForeignKeysForReferenceField(
                      embFieldMapping, embFmd, autoMode, storeMgr, clr);
              foreignKeys.addAll(fks);
            } else if (storeMgr
                        .getNucleusContext()
                        .getMetaDataManager()
                        .getMetaDataForClass(embFmd.getType(), clr)
                    != null
                && embFieldMapping.getNumberOfDatastoreMappings() > 0
                && embFieldMapping instanceof PersistableMapping) {
              // Field is for a PC class with the FK at this side, so add a FK to the table of this
              // PC
              ForeignKey fk =
                  TableUtils.getForeignKeyForPCField(
                      embFieldMapping, embFmd, autoMode, storeMgr, clr);
              if (fk != null) {
                foreignKeys.add(fk);
              }
            }
          }
        } else if (mmd.getMap().valueIsPersistent()) {
          // FK from join table to value table
          referencedTable = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr);
          if (referencedTable != null) {
            // Take <foreign-key> from <value>
            ForeignKeyMetaData fkmd = null;
            if (mmd.getValueMetaData() != null) {
              fkmd = mmd.getValueMetaData().getForeignKeyMetaData();
            }
            if (fkmd != null || autoMode) {
              ForeignKey fk = new ForeignKey(valueMapping, dba, referencedTable, true);
              fk.setForMetaData(fkmd);
              foreignKeys.add(fk);
            }
          }
        }
      }

      if (!isSerialisedKeyPC()) {
        if (isEmbeddedKeyPC()) {
          // Add any FKs for the fields of the (embedded) key
          EmbeddedKeyPCMapping embMapping = (EmbeddedKeyPCMapping) keyMapping;
          for (int i = 0; i < embMapping.getNumberOfJavaTypeMappings(); i++) {
            JavaTypeMapping embFieldMapping = embMapping.getJavaTypeMapping(i);
            AbstractMemberMetaData embFmd = embFieldMapping.getMemberMetaData();
            if (ClassUtils.isReferenceType(embFmd.getType())
                && embFieldMapping instanceof ReferenceMapping) {
              // Field is a reference type, so add a FK to the table of the PC for each PC
              // implementation
              Collection fks =
                  TableUtils.getForeignKeysForReferenceField(
                      embFieldMapping, embFmd, autoMode, storeMgr, clr);
              foreignKeys.addAll(fks);
            } else if (storeMgr
                        .getNucleusContext()
                        .getMetaDataManager()
                        .getMetaDataForClass(embFmd.getType(), clr)
                    != null
                && embFieldMapping.getNumberOfDatastoreMappings() > 0
                && embFieldMapping instanceof PersistableMapping) {
              // Field is for a PC class with the FK at this side, so add a FK to the table of this
              // PC
              ForeignKey fk =
                  TableUtils.getForeignKeyForPCField(
                      embFieldMapping, embFmd, autoMode, storeMgr, clr);
              if (fk != null) {
                foreignKeys.add(fk);
              }
            }
          }
        } else if (mmd.getMap().keyIsPersistent()) {
          // FK from join table to key table
          referencedTable = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
          if (referencedTable != null) {
            // Take <foreign-key> from <key>
            ForeignKeyMetaData fkmd = null;
            if (mmd.getKeyMetaData() != null) {
              fkmd = mmd.getKeyMetaData().getForeignKeyMetaData();
            }
            if (fkmd != null || autoMode) {
              ForeignKey fk = new ForeignKey(keyMapping, dba, referencedTable, true);
              fk.setForMetaData(fkmd);
              foreignKeys.add(fk);
            }
          }
        }
      }
    } catch (NoTableManagedException e) {
      // expected when no table exists
    }
    return foreignKeys;
  }
Пример #6
0
  /**
   * Method to initialise the table definition.
   *
   * @param clr The ClassLoaderResolver
   */
  public void initialize(ClassLoaderResolver clr) {
    assertIsUninitialized();

    MapMetaData mapmd = mmd.getMap();
    if (mapmd == null) {
      throw new NucleusUserException(LOCALISER.msg("057017", mmd));
    }

    PrimaryKeyMetaData pkmd =
        (mmd.getJoinMetaData() != null ? mmd.getJoinMetaData().getPrimaryKeyMetaData() : null);
    boolean pkColsSpecified = (pkmd != null && pkmd.getColumnMetaData() != null);
    boolean pkRequired = requiresPrimaryKey();

    // Add owner mapping
    ColumnMetaData[] ownerColmd = null;
    if (mmd.getJoinMetaData() != null
        && mmd.getJoinMetaData().getColumnMetaData() != null
        && mmd.getJoinMetaData().getColumnMetaData().length > 0) {
      // Column mappings defined at this side (1-N, M-N)
      // When specified at this side they use the <join> tag
      ownerColmd = mmd.getJoinMetaData().getColumnMetaData();
    }
    ownerMapping =
        ColumnCreator.createColumnsForJoinTables(
            clr.classForName(ownerType),
            mmd,
            ownerColmd,
            storeMgr,
            this,
            pkRequired,
            false,
            FieldRole.ROLE_OWNER,
            clr);
    if (NucleusLogger.DATASTORE.isDebugEnabled()) {
      debugMapping(ownerMapping);
    }

    String keyValueFieldName =
        (mmd.getKeyMetaData() != null ? mmd.getKeyMetaData().getMappedBy() : null);
    String valueKeyFieldName =
        (mmd.getValueMetaData() != null ? mmd.getValueMetaData().getMappedBy() : null);

    // Add key mapping
    boolean keyPC = (mmd.hasMap() && mmd.getMap().keyIsPersistent());
    Class keyCls = clr.classForName(mapmd.getKeyType());
    if (keyValueFieldName != null && isEmbeddedValuePC()) {
      // Added in value code
    } else if (isSerialisedKey()
        || isEmbeddedKeyPC()
        || (isEmbeddedKey() && !keyPC)
        || ClassUtils.isReferenceType(keyCls)) {
      // Key = PC(embedded), PC(serialised), Non-PC(serialised), Non-PC(embedded), Reference
      keyMapping = storeMgr.getMappingManager().getMapping(this, mmd, clr, FieldRole.ROLE_MAP_KEY);
      if (Boolean.TRUE.equals(mmd.getContainer().allowNulls())) {
        // Make all key col(s) nullable so we can store null elements
        for (int i = 0; i < keyMapping.getNumberOfDatastoreMappings(); i++) {
          Column elementCol = (Column) keyMapping.getDatastoreMapping(i).getDatastoreField();
          elementCol.setNullable();
        }
      }
      if (NucleusLogger.DATASTORE.isDebugEnabled()) {
        debugMapping(keyMapping);
      }
      if (valueKeyFieldName != null && isEmbeddedKeyPC()) {
        // Key (PC) is embedded and value is a field of the key
        EmbeddedKeyPCMapping embMapping = (EmbeddedKeyPCMapping) keyMapping;
        valueMapping = embMapping.getJavaTypeMapping(valueKeyFieldName);
      }
    } else {
      // Key = PC
      ColumnMetaData[] keyColmd = null;
      KeyMetaData keymd = mmd.getKeyMetaData();
      if (keymd != null
          && keymd.getColumnMetaData() != null
          && keymd.getColumnMetaData().length > 0) {
        // Column mappings defined at this side (1-N, M-N)
        keyColmd = keymd.getColumnMetaData();
      }
      keyMapping =
          ColumnCreator.createColumnsForJoinTables(
              keyCls, mmd, keyColmd, storeMgr, this, false, false, FieldRole.ROLE_MAP_KEY, clr);
      if (mmd.getContainer().allowNulls() == Boolean.TRUE) {
        // Make all key col(s) nullable so we can store null elements
        for (int i = 0; i < keyMapping.getNumberOfDatastoreMappings(); i++) {
          Column elementCol = (Column) keyMapping.getDatastoreMapping(i).getDatastoreField();
          elementCol.setNullable();
        }
      }
      if (NucleusLogger.DATASTORE.isDebugEnabled()) {
        debugMapping(keyMapping);
      }
    }

    // Add value mapping
    boolean valuePC = (mmd.hasMap() && mmd.getMap().valueIsPersistent());
    Class valueCls = clr.classForName(mapmd.getValueType());
    if (valueKeyFieldName != null && isEmbeddedKeyPC()) {
      // Added in key code
    } else if (isSerialisedValue()
        || isEmbeddedValuePC()
        || (isEmbeddedValue() && !valuePC)
        || ClassUtils.isReferenceType(valueCls)) {
      // Value = PC(embedded), PC(serialised), Non-PC(serialised), Non-PC(embedded), Reference
      valueMapping =
          storeMgr.getMappingManager().getMapping(this, mmd, clr, FieldRole.ROLE_MAP_VALUE);
      if (mmd.getContainer().allowNulls() == Boolean.TRUE) {
        // Make all value col(s) nullable so we can store null elements
        for (int i = 0; i < valueMapping.getNumberOfDatastoreMappings(); i++) {
          Column elementCol = (Column) valueMapping.getDatastoreMapping(i).getDatastoreField();
          elementCol.setNullable();
        }
      }
      if (NucleusLogger.DATASTORE.isDebugEnabled()) {
        debugMapping(valueMapping);
      }
      if (keyValueFieldName != null && isEmbeddedValuePC()) {
        // Value (PC) is embedded and key is a field of the value
        EmbeddedValuePCMapping embMapping = (EmbeddedValuePCMapping) valueMapping;
        keyMapping = embMapping.getJavaTypeMapping(keyValueFieldName);
      }
    } else {
      // Value = PC
      ColumnMetaData[] valueColmd = null;
      ValueMetaData valuemd = mmd.getValueMetaData();
      if (valuemd != null
          && valuemd.getColumnMetaData() != null
          && valuemd.getColumnMetaData().length > 0) {
        // Column mappings defined at this side (1-N, M-N)
        valueColmd = valuemd.getColumnMetaData();
      }
      valueMapping =
          ColumnCreator.createColumnsForJoinTables(
              clr.classForName(mapmd.getValueType()),
              mmd,
              valueColmd,
              storeMgr,
              this,
              false,
              true,
              FieldRole.ROLE_MAP_VALUE,
              clr);
      if (mmd.getContainer().allowNulls() == Boolean.TRUE) {
        // Make all value col(s) nullable so we can store null elements
        for (int i = 0; i < valueMapping.getNumberOfDatastoreMappings(); i++) {
          Column elementCol = (Column) valueMapping.getDatastoreMapping(i).getDatastoreField();
          elementCol.setNullable();
        }
      }
      if (NucleusLogger.DATASTORE.isDebugEnabled()) {
        debugMapping(valueMapping);
      }
    }

    // Add order mapping if required
    boolean orderRequired = false;
    if (mmd.getOrderMetaData() != null) {
      // User requested order column so add one
      orderRequired = true;
    } else if (requiresPrimaryKey() && !pkColsSpecified) {
      // PK is required so maybe need to add an index to form the PK
      if (isEmbeddedKeyPC()) {
        if (mmd.getMap().getKeyClassMetaData(clr, storeMgr.getMetaDataManager()).getIdentityType()
            != IdentityType.APPLICATION) {
          // Embedded key PC with datastore id so we need an index to form the PK
          orderRequired = true;
        }
      } else if (isSerialisedKey()) {
        // Serialised key, so need an index to form the PK
        orderRequired = true;
      } else if (keyMapping instanceof ReferenceMapping) {
        // ReferenceMapping, so have order if more than 1 implementation
        ReferenceMapping refMapping = (ReferenceMapping) keyMapping;
        if (refMapping.getJavaTypeMapping().length > 1) {
          orderRequired = true;
        }
      } else if (!(keyMapping instanceof PersistableMapping)) {
        // Non-PC, so depends if the key column can be used as part of a PK
        // TODO This assumes the keyMapping has a single column but what if it is Color with 4 cols?
        Column elementCol = (Column) keyMapping.getDatastoreMapping(0).getDatastoreField();
        if (!((RDBMSAdapter) storeMgr.getDatastoreAdapter())
            .isValidPrimaryKeyType(elementCol.getJdbcType())) {
          // Not possible to use this Non-PC type as part of the PK
          orderRequired = true;
        }
      }
    }
    if (orderRequired) {
      // Order/Adapter (index) column is required (integer based)
      ColumnMetaData orderColmd = null;
      if (mmd.getOrderMetaData() != null
          && mmd.getOrderMetaData().getColumnMetaData() != null
          && mmd.getOrderMetaData().getColumnMetaData().length > 0) {
        // Specified "order" column info
        orderColmd = mmd.getOrderMetaData().getColumnMetaData()[0];
        if (orderColmd.getName() == null) {
          orderColmd = new ColumnMetaData(orderColmd);
          if (mmd.hasExtension("adapter-column-name")) {
            // Specified "extension" column name
            // TODO Is this needed? The user can just specify <order column="...">
            orderColmd.setName(mmd.getValueForExtension("adapter-column-name"));
          } else {
            // No column name so use default
            DatastoreIdentifier id = storeMgr.getIdentifierFactory().newIndexFieldIdentifier(mmd);
            orderColmd.setName(id.getIdentifierName());
          }
        }
      } else {
        if (mmd.hasExtension("adapter-column-name")) {
          // Specified "extension" column name
          // TODO Is this needed? The user can just specify <order column="...">
          orderColmd = new ColumnMetaData();
          orderColmd.setName(mmd.getValueForExtension("adapter-column-name"));
        } else {
          // No column name so use default
          DatastoreIdentifier id = storeMgr.getIdentifierFactory().newIndexFieldIdentifier(mmd);
          orderColmd = new ColumnMetaData();
          orderColmd.setName(id.getIdentifierName());
        }
      }
      orderMapping =
          storeMgr
              .getMappingManager()
              .getMapping(int.class); // JDO2 spec [18.5] order column is assumed to be "int"
      ColumnCreator.createIndexColumn(
          orderMapping, storeMgr, clr, this, orderColmd, pkRequired && !pkColsSpecified);
      if (NucleusLogger.DATASTORE.isDebugEnabled()) {
        debugMapping(orderMapping);
      }
    }

    // Define primary key of the join table (if any)
    if (pkRequired) {
      if (pkColsSpecified) {
        // Apply the users PK specification
        applyUserPrimaryKeySpecification(pkmd);
      } else {
        // Define PK using JPOX rules
        if (orderRequired) {
          // Order column specified so owner+order are the PK
          orderMapping.getDatastoreMapping(0).getDatastoreField().setAsPrimaryKey();
        } else {
          // No order column specified so owner+key are the PK
          for (int i = 0; i < keyMapping.getNumberOfDatastoreMappings(); i++) {
            keyMapping.getDatastoreMapping(i).getDatastoreField().setAsPrimaryKey();
          }
        }
      }
    }

    state = TABLE_STATE_INITIALIZED;
  }