예제 #1
0
  /**
   * Accessor for the indices for this table. This includes both the user-defined indices (via
   * MetaData), and the ones required by foreign keys.
   *
   * @param clr The ClassLoaderResolver
   * @return The indices
   */
  protected Set getExpectedIndices(ClassLoaderResolver clr) {
    Set indices = new HashSet();

    // Index for FK back to owner
    if (mmd.getIndexMetaData() != null) {
      Index index = TableUtils.getIndexForField(this, mmd.getIndexMetaData(), ownerMapping);
      if (index != null) {
        indices.add(index);
      }
    } else if (mmd.getJoinMetaData() != null && mmd.getJoinMetaData().getIndexMetaData() != null) {
      Index index =
          TableUtils.getIndexForField(this, mmd.getJoinMetaData().getIndexMetaData(), ownerMapping);
      if (index != null) {
        indices.add(index);
      }
    } else {
      // Fallback to an index for the foreign-key to the owner
      Index index = TableUtils.getIndexForField(this, null, ownerMapping);
      if (index != null) {
        indices.add(index);
      }
    }

    // Index for the key FK (if required)
    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);
          }
        }
      }
    } else {
      KeyMetaData keymd = mmd.getKeyMetaData();
      if (keymd != null && keymd.getIndexMetaData() != null) {
        IndexMetaData idxmd = mmd.getKeyMetaData().getIndexMetaData();
        Index index = TableUtils.getIndexForField(this, idxmd, keyMapping);
        if (index != null) {
          indices.add(index);
        }
      } else {
        // Fallback to an index for any foreign-key to the key
        if (keyMapping instanceof PersistableMapping) {
          Index index = TableUtils.getIndexForField(this, null, keyMapping);
          if (index != null) {
            indices.add(index);
          }
        }
      }
    }

    // Index for the value FK (if required)
    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);
          }
        }
      }
    } else {
      ValueMetaData valmd = mmd.getValueMetaData();
      if (valmd != null && valmd.getIndexMetaData() != null) {
        IndexMetaData idxmd = mmd.getValueMetaData().getIndexMetaData();
        Index index = TableUtils.getIndexForField(this, idxmd, valueMapping);
        if (index != null) {
          indices.add(index);
        }
      } else {
        // Fallback to an index for any foreign-key to the value
        if (valueMapping instanceof PersistableMapping) {
          Index index = TableUtils.getIndexForField(this, null, valueMapping);
          if (index != null) {
            indices.add(index);
          }
        }
      }
    }

    return indices;
  }
예제 #2
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()) {
      logMapping(mmd.getFullFieldName() + ".[OWNER]", 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 = keyMapping.getDatastoreMapping(i).getColumn();
          elementCol.setNullable(true);
        }
      }
      if (NucleusLogger.DATASTORE.isDebugEnabled()) {
        logMapping(mmd.getFullFieldName() + ".[KEY]", 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 = keyMapping.getDatastoreMapping(i).getColumn();
          elementCol.setNullable(true);
        }
      }
      if (NucleusLogger.DATASTORE.isDebugEnabled()) {
        logMapping(mmd.getFullFieldName() + ".[KEY]", 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 = valueMapping.getDatastoreMapping(i).getColumn();
          elementCol.setNullable(true);
        }
      }
      if (NucleusLogger.DATASTORE.isDebugEnabled()) {
        logMapping(mmd.getFullFieldName() + ".[VALUE]", 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 = valueMapping.getDatastoreMapping(i).getColumn();
          elementCol.setNullable(true);
        }
      }
      if (NucleusLogger.DATASTORE.isDebugEnabled()) {
        logMapping(mmd.getFullFieldName() + ".[VALUE]", 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 = keyMapping.getDatastoreMapping(0).getColumn();
        if (!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) {
          // No column name so use default
          orderColmd = new ColumnMetaData(orderColmd);
          DatastoreIdentifier id = storeMgr.getIdentifierFactory().newIndexFieldIdentifier(mmd);
          orderColmd.setName(id.getName());
        }
      } else {
        // No column name so use default
        DatastoreIdentifier id = storeMgr.getIdentifierFactory().newIndexFieldIdentifier(mmd);
        orderColmd = new ColumnMetaData();
        orderColmd.setName(id.getName());
      }
      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()) {
        logMapping(mmd.getFullFieldName() + ".[ORDER]", 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 internal rules
        if (orderRequired) {
          // Order column specified so owner+order are the PK
          orderMapping.getDatastoreMapping(0).getColumn().setPrimaryKey();
        } else {
          // No order column specified so owner+key are the PK
          for (int i = 0; i < keyMapping.getNumberOfDatastoreMappings(); i++) {
            keyMapping.getDatastoreMapping(i).getColumn().setPrimaryKey();
          }
        }
      }
    }

    if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled()) {
      NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("057023", this));
    }
    storeMgr.registerTableInitialized(this);
    state = TABLE_STATE_INITIALIZED;
  }