All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.db4o.YapClassCollection Maven / Gradle / Ivy

The newest version!
/* Copyright (C) 2004 - 2005  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;

import com.db4o.ext.*;
import com.db4o.foundation.*;
import com.db4o.reflect.*;

/**
 */
public final class YapClassCollection extends YapMeta implements UseSystemTransaction {

    private YapClass i_addingMembersTo;

    private Collection4 i_classes;
    private Hashtable4 i_creating;
    
    final YapStream i_stream;
    final Transaction i_systemTrans;

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


    YapClassCollection(Transaction a_trans) {
        i_systemTrans = a_trans;
        i_stream = a_trans.i_stream;
        i_initYapClassesOnUp = new Queue4();
		_classInits = new PendingClassInits(this);
    }

    void addYapClass(YapClass yapClass) {
        i_stream.setDirty(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(i_systemTrans);
        }
        i_yapClassByID.put(yapClass.getID(), yapClass);
    }
    
    private byte[] asBytes(String str){
        return i_stream.stringIO().write(str);
    }

    void attachQueryNode(final String fieldName, final Visitor4 a_visitor) {
        YapClassCollectionIterator i = iterator();
        while (i.hasNext()) {
            final YapClass yc = i.readNextClass();
            if(! yc.isInternal()){
                yc.forEachYapField(new Visitor4() {
                    public void visit(Object obj) {
                        YapField yf = (YapField)obj;
                        if(yf.canAddToQuery(fieldName)){
                            a_visitor.visit(new Object[] {yc, yf});
                        }
                    }
                });
            }
        }
    }

    void checkChanges() {
        Iterator4 i = i_classes.iterator();
        while (i.hasNext()) {
            ((YapClass)i.next()).checkChanges();
        }
    }
    
    final boolean createYapClass(YapClass a_yapClass, ReflectClass a_class) {
        i_yapClassCreationDepth++;
        ReflectClass superClass = a_class.getSuperclass();
        YapClass superYapClass = null;
        if (superClass != null && ! superClass.equals(i_stream.i_handlers.ICLASS_OBJECT)) {
            superYapClass = getYapClass(superClass, true);
        }
        boolean ret = i_stream.createYapClass(a_yapClass, a_class, superYapClass);
        i_yapClassCreationDepth--;
        initYapClassesOnUp();
        return ret;
    }


    boolean fieldExists(String a_field) {
        YapClassCollectionIterator i = iterator();
        while (i.hasNext()) {
            if (i.readNextClass().getYapField(a_field) != null) {
                return true;
            }
        }
        return false;
    }

    Collection4 forInterface(ReflectClass claxx) {
        Collection4 col = new Collection4();
        YapClassCollectionIterator i = iterator();
        while (i.hasNext()) {
            YapClass yc = i.readNextClass();
            ReflectClass candidate = yc.classReflector();
            if(! candidate.isInterface()){
                if (claxx.isAssignableFrom(candidate)) {
                    col.add(yc);
                    Iterator4 j = col.iterator();
                    while (j.hasNext()) {
                        YapClass existing = (YapClass)j.next();
                        if(existing != yc){
                            YapClass higher = yc.getHigherHierarchy(existing);
                            if (higher != null) {
                                if (higher == yc) {
                                    col.remove(existing);
                                }else{
                                    col.remove(yc);
                                }
                            }
                        }
                    }
                }
            }
        }
        return col;
    }

    byte getIdentifier() {
        return YapConst.YAPCLASSCOLLECTION;
    }
    
    YapClass getActiveYapClass(ReflectClass a_class) {
        return (YapClass)i_yapClassByClass.get(a_class);
    }

    YapClass getYapClass(ReflectClass a_class, boolean a_create) {
        YapClass yapClass = (YapClass)i_yapClassByClass.get(a_class);
        
        if (yapClass == null) {
            yapClass = (YapClass)i_yapClassByBytes.remove(asBytes(a_class.getName()));
            readYapClass(yapClass, a_class);
        }

        if (yapClass != null || (!a_create)) {
            return yapClass;
        }
        
        yapClass = (YapClass)i_creating.get(a_class);
        
        if(yapClass != null){
            return yapClass;
        }
        
        yapClass = new YapClass(i_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(i_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);
        
        i_stream.setDirty(this);
        
        return yapClass;
    }

    YapClass getYapClass(int a_id) {
        return readYapClass((YapClass)i_yapClassByID.get(a_id), null);
    }

    public YapClass getYapClass(String a_name) {
        YapClass yapClass = (YapClass)i_yapClassByBytes.remove(asBytes(a_name));
        readYapClass(yapClass, null);
        if (yapClass == null) {
            YapClassCollectionIterator i = iterator();
            while (i.hasNext()) {
                yapClass = (YapClass)i.next();
                if (a_name.equals(yapClass.getName())) {
                    readYapClass(yapClass, null);
                    return yapClass;
                }
            }
            return null;
        }
        return yapClass;
    }
    
    public int getYapClassID(String name){
        YapClass yc = (YapClass)i_yapClassByBytes.get(asBytes(name));
        if(yc != null){
            return yc.getID();
        }
        return 0;
    }

    void initOnUp(Transaction systemTrans) {
        i_yapClassCreationDepth++;
        systemTrans.i_stream.showInternalClasses(true);
        Iterator4 i = i_classes.iterator();
        while (i.hasNext()) {
            ((YapClass)i.next()).initOnUp(systemTrans);
        }
        systemTrans.i_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){
            YapClass yc = (YapClass)i_initYapClassesOnUp.next();
            while(yc != null){
                yc.initOnUp(i_systemTrans);
                yc = (YapClass)i_initYapClassesOnUp.next();
            }
        }
    }
    
    YapClassCollectionIterator iterator(){
        return new YapClassCollectionIterator(this, i_classes._first);
    }

    int ownLength() {
        return YapConst.OBJECT_LENGTH
            + YapConst.YAPINT_LENGTH
            + (i_classes.size() * YapConst.YAPID_LENGTH);
    }

    void purge() {
        Iterator4 i = i_classes.iterator();
        while (i.hasNext()) {
            ((YapClass)i.next()).purge();
        }
    }

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

        initTables(classCount);

        for (int i = classCount; i > 0; i--) {
            YapClass yapClass = new YapClass(i_stream, null);
            int id = a_reader.readInt();
            yapClass.setID(i_stream, id);
            i_classes.add(yapClass);
            i_yapClassByID.put(id, yapClass);
            i_yapClassByBytes.put(yapClass.readName(a_trans), yapClass);
        }
        
        final Hashtable4 readAs = i_stream.i_config._readAs; 
        
        readAs.forEachKey(new Visitor4() {
            public void visit(Object a_object) {
                String dbName = (String)a_object;
                byte[] dbbytes = asBytes(dbName);
                String useName = (String)readAs.get(dbName);
                byte[] useBytes = asBytes(useName);
                if(i_yapClassByBytes.get(useBytes) == null){
                    YapClass yc = (YapClass)i_yapClassByBytes.get(dbbytes);
                    if(yc != null){
                        yc.i_nameBytes = useBytes;
                        yc.setConfig(i_stream.i_config.configClass(dbName));
                        i_yapClassByBytes.put(dbbytes, null);
                        i_yapClassByBytes.put(useBytes, yc);
                    }else{
                        int xxx = 1;
                    }
                }
            }
        });
    }

    YapClass readYapClass(YapClass yapClass, ReflectClass a_class) {
        if (yapClass != null  && ! yapClass.stateUnread()) {
            return yapClass;
        }
        i_yapClassCreationDepth++;
        if (yapClass != null  && yapClass.stateUnread()) {
            yapClass.createConfigAndConstructor(i_yapClassByBytes, i_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;
    }

    void refreshClasses() {
        YapClassCollection rereader = new YapClassCollection(i_systemTrans);
        rereader.i_id = i_id;
        rereader.read(i_stream.getSystemTransaction());
        Iterator4 i = rereader.i_classes.iterator();
        while (i.hasNext()) {
            YapClass yc = (YapClass)i.next();
            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(i_systemTrans), yc);
                }else{
                    i_yapClassByClass.put(yc.classReflector(), yc);
                }
            }
        }
        i = i_classes.iterator();
        while (i.hasNext()) {
            YapClass yc = (YapClass)i.next();
            yc.refresh();
        }
    }

    void reReadYapClass(YapClass yapClass){
        if(yapClass != null){
            reReadYapClass(yapClass.i_ancestor);
            yapClass.readName(i_systemTrans);
            yapClass.forceRead();
            yapClass.setStateClean();
            yapClass.bitFalse(YapConst.CHECKED_CHANGES);
            yapClass.bitFalse(YapConst.READING);
            yapClass.bitFalse(YapConst.CONTINUE);
            yapClass.bitFalse(YapConst.DEAD);
            yapClass.checkChanges();
        }
    }
    
    public StoredClass[] storedClasses() {
        Collection4 classes = new Collection4();
        Iterator4 i = i_classes.iterator();
        while (i.hasNext()) {
            YapClass yc = (YapClass)i.next();
            readYapClass(yc, null);
            if(yc.classReflector() == null){
                yc.forceRead();
            }
            classes.add(yc);
        }
        StoredClass[] sclasses = new StoredClass[classes.size()];
        classes.toArray(sclasses);
        return sclasses;
    }

    void writeThis(YapWriter a_writer) {
        a_writer.writeInt(i_classes.size());
        Iterator4 i = i_classes.iterator();
        while (i.hasNext()) {
            writeIDOf((YapClass)i.next(), a_writer);
        }
    }

	public String toString(){
        if(! Debug4.prettyToStrings){
            return super.toString();
        }
		String str = "";
		Iterator4 i = i_classes.iterator();
		while(i.hasNext()){
			YapClass yc = (YapClass)i.next();
			str += yc.getID() + " " + yc + "\r\n";
		}
		return str;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy