Package com.db4o.internal

Source Code of com.db4o.internal.ClassMetadataRepository

/* Copyright (C) 2004 - 2006  db4objects Inc.  http://www.db4o.com

This file is part of the db4o open source object database.

db4o is free software; you can redistribute it and/or modify it under
the terms of version 2 of the GNU General Public License as published
by the Free Software Foundation and as clarified by db4objects' GPL
interpretation policy, available at
http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
Suite 350, San Mateo, CA 94403, USA.

db4o is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */
package com.db4o.internal;

import com.db4o.*;
import com.db4o.ext.StoredClass;
import com.db4o.foundation.ArrayIterator4;
import com.db4o.foundation.Collection4;
import com.db4o.foundation.Debug4;
import com.db4o.foundation.Hashtable4;
import com.db4o.foundation.Iterator4;
import com.db4o.foundation.MappingIterator;
import com.db4o.foundation.Queue4;
import com.db4o.foundation.Visitor4;
import com.db4o.reflect.ReflectClass;


/**
* @exclude
*/
public final class ClassMetadataRepository extends PersistentBase {

    private Collection4 i_classes;
    private Hashtable4 i_creating;
   
    private final Transaction _systemTransaction;

    private Hashtable4 i_yapClassByBytes;
    private Hashtable4 i_yapClassByClass;
    private Hashtable4 i_yapClassByID;
   
    private int i_yapClassCreationDepth;
    private Queue4 i_initYapClassesOnUp;
 
  private final PendingClassInits _classInits;


    ClassMetadataRepository(Transaction systemTransaction) {
        _systemTransaction = systemTransaction;
        i_initYapClassesOnUp = new Queue4();
    _classInits = new PendingClassInits(_systemTransaction);
    }

    public void addYapClass(ClassMetadata yapClass) {
        stream().setDirtyInSystemTransaction(this);
        i_classes.add(yapClass);
        if(yapClass.stateUnread()){
            i_yapClassByBytes.put(yapClass.i_nameBytes, yapClass);
        }else{
            i_yapClassByClass.put(yapClass.classReflector(), yapClass);
        }
        if (yapClass.getID() == 0) {
            yapClass.write(_systemTransaction);
        }
        i_yapClassByID.put(yapClass.getID(), yapClass);
    }
   
    private byte[] asBytes(String str){
        return stream().stringIO().write(str);
    }

    public void attachQueryNode(final String fieldName, final Visitor4 a_visitor) {
        ClassMetadataIterator i = iterator();
        while (i.moveNext()) {
            final ClassMetadata yc = i.currentClass();
            if(! yc.isInternal()){
                yc.forEachYapField(new Visitor4() {
                    public void visit(Object obj) {
                        FieldMetadata yf = (FieldMetadata)obj;
                        if(yf.canAddToQuery(fieldName)){
                            a_visitor.visit(new Object[] {yc, yf});
                        }
                    }
                });
            }
        }
    }

    void checkChanges() {
        Iterator4 i = i_classes.iterator();
        while (i.moveNext()) {
            ((ClassMetadata)i.current()).checkChanges();
        }
    }
   
    final boolean createYapClass(ClassMetadata a_yapClass, ReflectClass a_class) {
        i_yapClassCreationDepth++;
        ReflectClass superClass = a_class.getSuperclass();
        ClassMetadata superYapClass = null;
        if (superClass != null && ! superClass.equals(stream().i_handlers.ICLASS_OBJECT)) {
            superYapClass = produceYapClass(superClass);
        }
        boolean ret = stream().createYapClass(a_yapClass, a_class, superYapClass);
        i_yapClassCreationDepth--;
        initYapClassesOnUp();
        return ret;
    }

  public static void defrag(ReaderPair readers) {
        if (Deploy.debug) {
            readers.readBegin(Const4.YAPCLASSCOLLECTION);
        }
    int numClasses=readers.readInt();
    for(int classIdx=0;classIdx<numClasses;classIdx++) {
      readers.copyID();
    }
        if (Deploy.debug) {
            readers.readEnd();
        }
  }

  private void ensureAllClassesRead() {
    boolean allClassesRead=false;
      while(!allClassesRead) {
        Collection4 unreadClasses=new Collection4();
      int numClasses=i_classes.size();
          Iterator4 classIter = i_classes.iterator();
          while(classIter.moveNext()) {
            ClassMetadata yapClass=(ClassMetadata)classIter.current();
            if(yapClass.stateUnread()) {
              unreadClasses.add(yapClass);
            }
          }
          Iterator4 unreadIter=unreadClasses.iterator();
          while(unreadIter.moveNext()) {
            ClassMetadata yapClass=(ClassMetadata)unreadIter.current();
            readYapClass(yapClass,null);
              if(yapClass.classReflector() == null){
                yapClass.forceRead();
              }
          }
          allClassesRead=(i_classes.size()==numClasses);
      }
    applyReadAs();
  }

    boolean fieldExists(String a_field) {
        ClassMetadataIterator i = iterator();
        while (i.moveNext()) {
            if (i.currentClass().getYapField(a_field) != null) {
                return true;
            }
        }
        return false;
    }

    public Collection4 forInterface(ReflectClass claxx) {
        Collection4 col = new Collection4();
        ClassMetadataIterator i = iterator();
        while (i.moveNext()) {
            ClassMetadata yc = i.currentClass();
            ReflectClass candidate = yc.classReflector();
            if(! candidate.isInterface()){
                if (claxx.isAssignableFrom(candidate)) {
                    col.add(yc);
                    Iterator4 j = new Collection4(col).iterator();
                    while (j.moveNext()) {
                        ClassMetadata existing = (ClassMetadata)j.current();
                        if(existing != yc){
                            ClassMetadata higher = yc.getHigherHierarchy(existing);
                            if (higher != null) {
                                if (higher == yc) {
                                    col.remove(existing);
                                }else{
                                    col.remove(yc);
                                }
                            }
                        }
                    }
                }
            }
        }
        return col;
    }

    public byte getIdentifier() {
        return Const4.YAPCLASSCOLLECTION;
    }
   
    ClassMetadata getActiveYapClass(ReflectClass a_class) {
        return (ClassMetadata)i_yapClassByClass.get(a_class);
    }
   
    ClassMetadata getYapClass (ReflectClass a_class) {
      ClassMetadata yapClass = (ClassMetadata)i_yapClassByClass.get(a_class);
        if (yapClass != null) {
          return yapClass;
        }
        yapClass = (ClassMetadata)i_yapClassByBytes.remove(getNameBytes(a_class.getName()));
        readYapClass(yapClass, a_class);
        return yapClass;
    }

    ClassMetadata produceYapClass(ReflectClass a_class) {
     
      ClassMetadata yapClass = getYapClass(a_class);
     
        if (yapClass != null ) {
            return yapClass;
        }
       
        yapClass = (ClassMetadata)i_creating.get(a_class);
       
        if(yapClass != null){
            return yapClass;
        }
       
        yapClass = new ClassMetadata(stream(), a_class);
       
        i_creating.put(a_class, yapClass);
       
        if(! createYapClass(yapClass, a_class)){
            i_creating.remove(a_class);
            return null;
        }

        // YapStream#createYapClass may add the YapClass already,
        // so we have to check again
       
        boolean addMembers = false;
       
        if (i_yapClassByClass.get(a_class) == null) {
            addYapClass(yapClass);
            addMembers = true;
        }
       
        int id = yapClass.getID();
        if(id == 0){
            yapClass.write(stream().getSystemTransaction());
            id = yapClass.getID();
        }
       
        if(i_yapClassByID.get(id) == null){
            i_yapClassByID.put(id, yapClass);
            addMembers = true;
        }
       
        if(addMembers || yapClass.i_fields == null){
      _classInits.process(yapClass);
        }
       
        i_creating.remove(a_class);
       
        stream().setDirtyInSystemTransaction(this);
       
        return yapClass;
    }   
   
  ClassMetadata getYapClass(int id) {
        return readYapClass((ClassMetadata)i_yapClassByID.get(id), null);
    }
 
    public ClassMetadata getYapClass(String a_name) {
        ClassMetadata yapClass = (ClassMetadata)i_yapClassByBytes.remove(getNameBytes(a_name));
        readYapClass(yapClass, null);
        if (yapClass == null) {
            ClassMetadataIterator i = iterator();
            while (i.moveNext()) {
                yapClass = (ClassMetadata)i.current();
                if (a_name.equals(yapClass.getName())) {
                    readYapClass(yapClass, null);
                    return yapClass;
                }
            }
            return null;
        }
        return yapClass;
    }
   
    public int getYapClassID(String name){
        ClassMetadata yc = (ClassMetadata)i_yapClassByBytes.get(getNameBytes(name));
        if(yc != null){
            return yc.getID();
        }
        return 0;
    }

  byte[] getNameBytes(String name) {   
    return asBytes(resolveAliasRuntimeName(name));
  }

  private String resolveAliasRuntimeName(String name) {
    return stream().configImpl().resolveAliasRuntimeName(name);
  }

    void initOnUp(Transaction systemTrans) {
        i_yapClassCreationDepth++;
        systemTrans.stream().showInternalClasses(true);
        try {
          Iterator4 i = i_classes.iterator();
          while (i.moveNext()) {
              ((ClassMetadata)i.current()).initOnUp(systemTrans);
          }
        } finally {
          systemTrans.stream().showInternalClasses(false);
        }
        i_yapClassCreationDepth--;
        initYapClassesOnUp();
    }

    void initTables(int a_size) {
        i_classes = new Collection4();
        i_yapClassByBytes = new Hashtable4(a_size);
        if (a_size < 16) {
            a_size = 16;
        }
        i_yapClassByClass = new Hashtable4(a_size);
        i_yapClassByID = new Hashtable4(a_size);
        i_creating = new Hashtable4(1);
    }
   
    private void initYapClassesOnUp() {
        if(i_yapClassCreationDepth == 0){
            ClassMetadata yc = (ClassMetadata)i_initYapClassesOnUp.next();
            while(yc != null){
                yc.initOnUp(_systemTransaction);
                yc = (ClassMetadata)i_initYapClassesOnUp.next();
            }
        }
    }
   
    public ClassMetadataIterator iterator(){
        return new ClassMetadataIterator(this, new ArrayIterator4(i_classes.toArray()));
    }

    private static class ClassIDIterator extends MappingIterator {

    public ClassIDIterator(Collection4 classes) {
      super(classes.iterator());
    }
     
      protected Object map(Object current) {
        return new Integer(((ClassMetadata)current).getID());
      }
    }
   
    public Iterator4 ids(){
        return new ClassIDIterator(i_classes);
    }

    public int ownLength() {
        return Const4.OBJECT_LENGTH
            + Const4.INT_LENGTH
            + (i_classes.size() * Const4.ID_LENGTH);
    }

    void purge() {
        Iterator4 i = i_classes.iterator();
        while (i.moveNext()) {
            ((ClassMetadata)i.current()).purge();
        }
    }

    public final void readThis(Transaction a_trans, Buffer a_reader) {
    int classCount = a_reader.readInt();

    initTables(classCount);

    ObjectContainerBase stream = stream();
    int[] ids = new int[classCount];

    for (int i = 0; i < classCount; ++i) {
      ids[i] = a_reader.readInt();
    }
    StatefulBuffer[] yapWriters = stream.readWritersByIDs(a_trans, ids);

    for (int i = 0; i < classCount; ++i) {
      ClassMetadata yapClass = new ClassMetadata(stream, null);
      yapClass.setID(ids[i]);
      i_classes.add(yapClass);
      i_yapClassByID.put(ids[i], yapClass);
      byte[] name = yapClass.readName1(a_trans, yapWriters[i]);
      i_yapClassByBytes.put(name, yapClass);
    }

    applyReadAs();

  }

  Hashtable4 classByBytes(){
      return i_yapClassByBytes;
    }
   
    private void applyReadAs(){
        final Hashtable4 readAs = stream().configImpl().readAs();
        readAs.forEachKey(new Visitor4() {
            public void visit(Object a_object) {
                String dbName = (String)a_object;
                byte[] dbbytes = getNameBytes(dbName);
                String useName = (String)readAs.get(dbName);
                byte[] useBytes = getNameBytes(useName);
                if(classByBytes().get(useBytes) == null){
                    ClassMetadata yc = (ClassMetadata)classByBytes().get(dbbytes);
                    if(yc != null){
                        yc.i_nameBytes = useBytes;
                        yc.setConfig(stream().configImpl().configClass(dbName));
                        classByBytes().put(dbbytes, null);
                        classByBytes().put(useBytes, yc);
                    }
                }
            }
        });
    }

    public ClassMetadata readYapClass(ClassMetadata yapClass, ReflectClass a_class) {
      if(yapClass == null){
        return null;
      }
        if (! yapClass.stateUnread()) {
            return yapClass;
        }
        i_yapClassCreationDepth++;
        yapClass.createConfigAndConstructor(i_yapClassByBytes, stream(), a_class);
        ReflectClass claxx = yapClass.classReflector();
        if(claxx != null){
            i_yapClassByClass.put(claxx, yapClass);
            yapClass.readThis();
            yapClass.checkChanges();
            i_initYapClassesOnUp.add(yapClass);
        }
        i_yapClassCreationDepth--;
        initYapClassesOnUp();
        return yapClass;
    }

    public void refreshClasses() {
        ClassMetadataRepository rereader = new ClassMetadataRepository(_systemTransaction);
        rereader.i_id = i_id;
        rereader.read(stream().getSystemTransaction());
        Iterator4 i = rereader.i_classes.iterator();
        while (i.moveNext()) {
            ClassMetadata yc = (ClassMetadata)i.current();
            if (i_yapClassByID.get(yc.getID()) == null) {
                i_classes.add(yc);
                i_yapClassByID.put(yc.getID(), yc);
                if(yc.stateUnread()){
                    i_yapClassByBytes.put(yc.readName(_systemTransaction), yc);
                }else{
                    i_yapClassByClass.put(yc.classReflector(), yc);
                }
            }
        }
        i = i_classes.iterator();
        while (i.moveNext()) {
            ClassMetadata yc = (ClassMetadata)i.current();
            yc.refresh();
        }
    }

    void reReadYapClass(ClassMetadata yapClass){
        if(yapClass != null){
            reReadYapClass(yapClass.i_ancestor);
            yapClass.readName(_systemTransaction);
            yapClass.forceRead();
            yapClass.setStateClean();
            yapClass.bitFalse(Const4.CHECKED_CHANGES);
            yapClass.bitFalse(Const4.READING);
            yapClass.bitFalse(Const4.CONTINUE);
            yapClass.bitFalse(Const4.DEAD);
            yapClass.checkChanges();
        }
    }
   
    public StoredClass[] storedClasses() {
      ensureAllClassesRead();
        StoredClass[] sclasses = new StoredClass[i_classes.size()];
        i_classes.toArray(sclasses);
        return sclasses;
    }

    public void writeAllClasses(){
        StoredClass[] storedClasses = storedClasses();
        for (int i = 0; i < storedClasses.length; i++) {
            ClassMetadata yc = (ClassMetadata)storedClasses[i];
            yc.setStateDirty();
        }
       
        for (int i = 0; i < storedClasses.length; i++) {
            ClassMetadata yc = (ClassMetadata)storedClasses[i];
            yc.write(_systemTransaction);
        }
    }

    public void writeThis(Transaction trans, Buffer a_writer) {
        a_writer.writeInt(i_classes.size());
        Iterator4 i = i_classes.iterator();
        while (i.moveNext()) {
            a_writer.writeIDOf(trans, i.current());
        }
    }

  public String toString(){
        if(! Debug4.prettyToStrings){
            return super.toString();
        }
    String str = "Active:\n";
    Iterator4 i = i_classes.iterator();
    while(i.moveNext()){
      ClassMetadata yc = (ClassMetadata)i.current();
      str += yc.getID() + " " + yc + "\n";
    }
    return str;
  }

    ObjectContainerBase stream() {
        return _systemTransaction.stream();
    }
   
    public void setID(int a_id) {
      if (stream().isClient()) {
        super.setID(a_id);
        return;
      }
     
        if(i_id == 0) {         
      systemData().classCollectionID(a_id);
        }
        super.setID(a_id);
    }

  private SystemData systemData() {
    return _systemTransaction.i_file.systemData();
  }

}
TOP

Related Classes of com.db4o.internal.ClassMetadataRepository

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.