/** * Method to load all unloaded fields in the FetchPlan. Recurses through the FetchPlan objects and * loads fields of sub-objects where needed. Used as a precursor to detaching objects at commit * since fields can't be loaded during the postCommit phase when the detach actually happens. * * @param state The FetchPlan state */ public void loadFieldsInFetchPlan(FetchPlanState state) { if ((flags & FLAG_LOADINGFPFIELDS) != 0) { // Already in the process of loading fields in this class so skip return; } flags |= FLAG_LOADINGFPFIELDS; try { // Load unloaded FetchPlan fields of this object loadUnloadedFieldsInFetchPlan(); // Recurse through all fields and do the same int[] fieldNumbers = ClassUtils.getFlagsSetTo(loadedFields, cmd.getAllMemberPositions(), true); if (fieldNumbers != null && fieldNumbers.length > 0) { // TODO Fix this to just access the fields of the FieldManager yet this actually does a // replaceField replaceFields( fieldNumbers, new LoadFieldManager(this, cmd.getSCOMutableMemberFlags(), myFP, state)); updateLevel2CacheForFields(fieldNumbers); } } finally { flags &= ~FLAG_LOADINGFPFIELDS; } }
/** * Method that will unload all fields that are not in the FetchPlan. This is typically for use * when the instance is being refreshed. */ public void unloadNonFetchPlanFields() { int[] fpFieldNumbers = myFP.getMemberNumbers(); int[] nonfpFieldNumbers = null; if (fpFieldNumbers == null || fpFieldNumbers.length == 0) { nonfpFieldNumbers = cmd.getAllMemberPositions(); } else { int fieldCount = cmd.getMemberCount(); if (fieldCount == fpFieldNumbers.length) { // No fields that arent in FetchPlan return; } nonfpFieldNumbers = new int[fieldCount - fpFieldNumbers.length]; int currentFPFieldIndex = 0; int j = 0; for (int i = 0; i < fieldCount; i++) { if (currentFPFieldIndex >= fpFieldNumbers.length) { // Past end of FetchPlan fields nonfpFieldNumbers[j++] = i; } else { if (fpFieldNumbers[currentFPFieldIndex] == i) { // FetchPlan field so move to next currentFPFieldIndex++; } else { nonfpFieldNumbers[j++] = i; } } } } // Mark all non-FetchPlan fields as unloaded for (int i = 0; i < nonfpFieldNumbers.length; i++) { loadedFields[nonfpFieldNumbers[i]] = false; } }
/** * Convenience accessor to return the field numbers for the input loaded and dirty field arrays. * * @param loadedFields Fields that were detached with the object * @param dirtyFields Fields that have been modified while detached * @return The field numbers of loaded or dirty fields */ protected int[] getFieldNumbersOfLoadedOrDirtyFields( boolean[] loadedFields, boolean[] dirtyFields) { // Find the number of fields that are loaded or dirty int numFields = 0; for (int i = 0; i < loadedFields.length; i++) { if (loadedFields[i] || dirtyFields[i]) { numFields++; } } int[] fieldNumbers = new int[numFields]; int n = 0; int[] allFieldNumbers = cmd.getAllMemberPositions(); for (int i = 0; i < loadedFields.length; i++) { if (loadedFields[i] || dirtyFields[i]) { fieldNumbers[n++] = allFieldNumbers[i]; } } return fieldNumbers; }
/* (non-Javadoc) * @see org.datanucleus.store.fieldmanager.AbstractFieldManager#fetchObjectField(int) */ @Override public Object fetchObjectField(int fieldNumber) { ClassLoaderResolver clr = ec.getClassLoaderResolver(); AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber); RelationType relationType = mmd.getRelationType(clr); EmbeddedMetaData embmd = mmds.get(0).getEmbeddedMetaData(); if (mmds.size() == 1 && embmd != null && embmd.getOwnerMember() != null && embmd.getOwnerMember().equals(mmd.getName())) { // Special case of this being a link back to the owner. TODO Repeat this for nested and their // owners ObjectProvider[] ownerOps = ec.getOwnersForEmbeddedObjectProvider(op); return (ownerOps != null && ownerOps.length > 0 ? ownerOps[0].getObject() : null); } if (relationType != RelationType.NONE && MetaDataUtils.getInstance() .isMemberEmbedded(ec.getMetaDataManager(), clr, mmd, relationType, null)) { // Embedded field if (RelationType.isRelationSingleValued(relationType)) { // TODO Cater for null value detection List<AbstractMemberMetaData> embMmds = new ArrayList<AbstractMemberMetaData>(mmds); embMmds.add(mmd); AbstractClassMetaData embCmd = ec.getMetaDataManager().getMetaDataForClass(mmd.getType(), clr); ObjectProvider embOP = ec.getNucleusContext() .getObjectProviderFactory() .newForEmbedded(ec, embCmd, op, fieldNumber); FieldManager ffm = new FetchEmbeddedFieldManager(embOP, result, embMmds, table); embOP.replaceFields(embCmd.getAllMemberPositions(), ffm); return embOP.getObject(); } } return fetchNonEmbeddedObjectField(mmd, relationType, clr); }
private static void addColumnsToScanForEmbeddedMember( Scan scan, List<AbstractMemberMetaData> embMmds, Table table, ExecutionContext ec) { AbstractMemberMetaData lastMmd = embMmds.get(embMmds.size() - 1); ClassLoaderResolver clr = ec.getClassLoaderResolver(); AbstractClassMetaData embCmd = ec.getMetaDataManager().getMetaDataForClass(lastMmd.getTypeName(), clr); int[] embMmdPosns = embCmd.getAllMemberPositions(); for (int i = 0; i < embMmdPosns.length; i++) { AbstractMemberMetaData embMmd = embCmd.getMetaDataForManagedMemberAtAbsolutePosition(i); List<AbstractMemberMetaData> subEmbMmds = new ArrayList<AbstractMemberMetaData>(embMmds); subEmbMmds.add(embMmd); RelationType relationType = embMmd.getRelationType(clr); MemberColumnMapping mapping = table.getMemberColumnMappingForEmbeddedMember(subEmbMmds); if (RelationType.isRelationSingleValued(relationType)) { addColumnsToScanForEmbeddedMember(scan, subEmbMmds, table, ec); } else { String familyName = HBaseUtils.getFamilyNameForColumn(mapping.getColumn(0)); String qualifName = HBaseUtils.getQualifierNameForColumn(mapping.getColumn(0)); scan.addColumn(familyName.getBytes(), qualifName.getBytes()); } } }