Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*-
   * See the file LICENSE for redistribution information.
   *
   * Copyright (c) 2002, 2013 Oracle and/or its affiliates.  All rights reserved.
   *
   */
  
  package com.sleepycat.persist.impl;
  
 import java.util.List;
 import java.util.Map;
 
Format for a composite key class. This class is similar to ComplexFormat in that a composite key class and other complex classes have fields, and the Accessor interface is used to access those fields. Composite key classes are different in the following ways: - The superclass must be Object. No inheritance is allowed. - All instance fields must be annotated with

Author(s):
Mark Hayes
KeyField:
which determines their order in the data bytes. - Although fields may be reference types (primitive wrappers or other simple reference types), they are stored as if they were primitives. No object format ID is stored, and the class of the object must be the declared classs of the field; i.e., no polymorphism is allowed for key fields. In other words, a composite key is stored as an ordinary tuple as defined in the com.sleepycat.bind.tuple package. This keeps the key small and gives it a well defined sort order. - If the key class implements Comparable, it is called by the Database btree comparator. It must therefore be available during JE recovery, before the store and catalog have been opened. To support this, this format can be constructed during recovery. A SimpleCatalog singleton instance is used to provide a catalog of simple types that is used by the composite key format. - When interacting with the Accessor, the composite key format treats the Accessor's non-key fields as its key fields. The Accessor's key fields are secondary keys, while the composite format's key fields are the component parts of a single key.
 
 public class CompositeKeyFormat extends Format {
 
     private static final long serialVersionUID = 306843428409314630L;
 
     private ClassMetadata metadata;
     private List<FieldInfofields;
     private transient Accessor objAccessor;
     private transient Accessor rawAccessor;
     private transient volatile Map<StringRawFieldrawFields;
     private transient volatile FieldInfo[] rawInputFields;
 
     static String[] getFieldNameArray(List<FieldMetadatalist) {
         int index = 0;
         String[] a = new String[list.size()];
         for (FieldMetadata f : list) {
             a[index] = f.getName();
             index += 1;
         }
         return a;
     }

    
Creates a new composite key format.
 
     CompositeKeyFormat(Catalog catalog,
                        Class cls,
                        ClassMetadata metadata,
                        List<FieldMetadatafieldMeta) {
         this(catalogclsmetadatagetFieldNameArray(fieldMeta));
     }

    
Reconsistitues a composite key format after a PersistComparator is deserialized.
 
     CompositeKeyFormat(Catalog catalogClass clsString[] fieldNames) {
         this(catalogclsnull /*metadata*/fieldNames);
     }
 
     private CompositeKeyFormat(Catalog catalog,
                                Class cls,
                               ClassMetadata metadata,
                               String[] fieldNames) {
        super(catalogcls);
        this. = metadata;
        /* Check that the superclass is Object. */
        Class superCls = cls.getSuperclass();
        if (superCls != Object.class) {
            throw new IllegalArgumentException
                ("Composite key class must be derived from Object: " +
                 cls.getName());
        }
        /* Populate fields list in fieldNames order. */
        List<FieldInfoinstanceFields =
            FieldInfo.getInstanceFields(clsmetadata);
         = new ArrayList<FieldInfo>(instanceFields.size());
        for (String fieldName : fieldNames) {
            FieldInfo field = null;
            for (FieldInfo tryField : instanceFields) {
                if (fieldName.equals(tryField.getName())) {
                    field = tryField;
                    break;
                }
            }
            if (field == null) {
                throw new IllegalArgumentException
                    ("Composite key field is not an instance field: " +
                     getClassName() + '.' + fieldName);
            }
            .add(field);
            instanceFields.remove(field);
            Class fieldCls = field.getFieldClass(getCatalog());
            if (!SimpleCatalog.isSimpleType(fieldCls) &&
                !fieldCls.isEnum()) {
                throw new IllegalArgumentException
                    ("Composite key field is not a simple type or enum: " +
                     getClassName() + '.' + fieldName);
            }
        }
        if (instanceFields.size() > 0) {
            throw new IllegalArgumentException
                ("All composite key instance fields must be key fields: " +
                 getClassName() + '.' + instanceFields.get(0).getName());
        }
    }
        return ;
    }
    @Override
    void migrateFromBeta(Map<StringFormatformatMap) {
        super.migrateFromBeta(formatMap);
        for (FieldInfo field : ) {
            field.migrateFromBeta(formatMap);
        }
    }
    @Override
    boolean isModelClass() {
        return true;
    }
    @Override
    public ClassMetadata getClassMetadata() {
        if ( == null) {
            throw DbCompat.unexpectedState(getClassName());
        }
        return ;
    }
    @Override
    public Map<StringRawFieldgetFields() {
        /*
         * Lazily create the raw type information.  Synchronization is not
         * required since this object is immutable.  If by chance we create two
         * maps when two threads execute this block, no harm is done.  But be
         * sure to assign the rawFields field only after the map is fully
         * populated.
         */
        if ( == null) {
            Map<StringRawFieldmap = new HashMap<StringRawField>();
            for (RawField field : ) {
                map.put(field.getName(), field);
            }
             = map;
        }
        return ;
    }
    @Override
    void collectRelatedFormats(Catalog catalog,
                               Map<StringFormatnewFormats) {
        /* Collect field formats. */
        for (FieldInfo field : ) {
            field.collectRelatedFormats(catalognewFormats);
        }
    }
    @Override
    void initialize(Catalog catalogEntityModel modelint initVersion) {
        /* Initialize all fields. */
        for (FieldInfo field : ) {
            field.initialize(catalogmodelinitVersion);
        }
        /* Create the accessor. */
        Class type = getType();
        if (type != null) {
            if (EnhancedAccessor.isEnhanced(type)) {
                 = new EnhancedAccessor(catalogtype);
            } else {
                 = new ReflectionAccessor(catalogtype);
            }
        }
         = new RawAccessor(this);
    }
    @Override
    Object newArray(int len) {
        return .newArray(len);
    }
    @Override
    public Object newInstance(EntityInput inputboolean rawAccess) {
        Accessor accessor = rawAccess ?  : ;
        return accessor.newInstance();
    }
    @Override
    public Object readObject(Object oEntityInput inputboolean rawAccess)
        throws RefreshException {
        Accessor accessor = rawAccess ?  : ;
        accessor.readCompositeKeyFields(oinput);
        return o;
    }
    @Override
    void writeObject(Object oEntityOutput outputboolean rawAccess)
        throws RefreshException {
        Accessor accessor = rawAccess ?  : ;
        accessor.writeCompositeKeyFields(ooutput);
    }
    @Override
                            boolean rawAccess,
                            RawObject rawObject,
                            IdentityHashMap converted)
        throws RefreshException {
        /*
         * Synchronization is not required since rawInputFields is immutable.
         * If by chance we create duplicate values when two threads execute
         * this block, no harm is done.  But be sure to assign the field only
         * after the values are fully populated.
         */
        FieldInfo[] myFields = ;
        if (myFields == null) {
            myFields = new FieldInfo[.size()];
            .toArray(myFields);
             = myFields;
        }
        if (rawObject.getSuper() != null) {
            throw new IllegalArgumentException
                ("RawObject has too many superclasses: " +
                 rawObject.getType().getClassName());
        }
        RawObject[] objects = new RawObject[myFields.length];
        Arrays.fill(objectsrawObject);
        EntityInput in = new RawComplexInput
            (catalograwAccessconvertedmyFieldsobjects);
        Object o = newInstance(inrawAccess);
        converted.put(rawObjecto);
        return readObject(oinrawAccess);
    }
    @Override
    void skipContents(RecordInput input)
        throws RefreshException {
        int maxNum = .size();
        for (int i = 0; i < maxNumi += 1) {
            .get(i).getType().skipContents(input);
        }
    }
    @Override
    void copySecKey(RecordInput inputRecordOutput output) {
        int maxNum = .size();
        for (int i = 0; i < maxNumi += 1) {
            .get(i).getType().copySecKey(inputoutput);
        }
    }
    @Override
        if (.size() != 1) {
            throw new IllegalArgumentException
                ("A composite key class used with a sequence may contain " +
                 "only a single key field: " + getClassName());
        }
        return .get(0).getType().getSequenceKeyFormat();
    }
    @Override
    boolean evolve(Format newFormatParamEvolver evolver) {
        /* Disallow evolution to a non-composite format. */
        if (!(newFormatParam instanceof CompositeKeyFormat)) {
            evolver.addEvolveError
                (thisnewFormatParamnull,
                 "A composite key class may not be changed to a different " +
                 "type");
            return false;
        }
        CompositeKeyFormat newFormat = (CompositeKeyFormatnewFormatParam;
        /* Check for added or removed key fields. */
        if (.size() != newFormat.fields.size()) {
            evolver.addEvolveError
                (thisnewFormat,
                 "Composite key class fields were added or removed ",
                 "Old fields: " +  +
                 " new fields: " + newFormat.fields);
            return false;
        }
        /* Check for modified key fields. */
        boolean newVersion = false;
        for (int i = 0; i < .size(); i += 1) {
            int result = evolver.evolveRequiredKeyField
                (thisnewFormat.get(i),
                 newFormat.fields.get(i));
            if (result == .) {
                return false;
            }
            if (result == .) {
                newVersion = true;
            }
        }
        /*
         * We never need to use a custom reader because the physical key field
         * formats never change.  But we do create a new evolved format when
         * a type changes (primitive <-> primitive wrapper) so that the new
         * type information is correct.
         */
        if (newVersion) {
            evolver.useEvolvedFormat(thisnewFormatnewFormat);
        } else {
            evolver.useOldFormat(thisnewFormat);
        }
        return true;
    }
New to GrepCode? Check out our FAQ X