alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.mdr.test;

import java.io.*;
import java.util.*;

import org.netbeans.api.mdr.*;
import org.openide.util.Lookup;
import org.netbeans.lib.jmi.xmi.*;
import org.netbeans.lib.jmi.util.*;

import javax.jmi.reflect.*;
import javax.jmi.model.*;

/**
 * Generates random data (instances, attribute values, links) in a given package.
 */

public class RandomDataSupport extends Object {
    
    // variables ................................................................

    // used random generator
    private Random random = new Random ();

    // extent in which random data are generated
    private RefPackage target;
    private HashSet trackedPackages = new HashSet();

    // maximal number of instances that should be generated per one class proxy
    private int maxInstancesPerClass;
    
    private RefClass[] allClasses;
    private RefAssociation[] allAssociations;
    private ArrayList toDelete;

    // stores the number of created instaces
    private int instancesCounter = 0;
    // stores the number of created links
    private int linksCounter = 0;
    private int othersCounter = 0;

    private ElementsCache elementsCache;

    private boolean warmUp;
    private boolean testRun;

    // init .....................................................................
    
    public RandomDataSupport(RefPackage pkg) {
        target = pkg;
        elementsCache = new ElementsCache (target);
        prepareAllClasses();
        prepareAllAssociations();
    }
    
    // methods ..................................................................
    
    /**
     * Generates random objects in given extent.
     *
     * @param target extent
     * @param randSeed value to initialize random generator with
     * @param max maximal number of instances that should be generated per one class proxy
     */
    public void generateObjects (long randSeed, int max, boolean warmUp, boolean testRun) {
        random.setSeed (randSeed);
        instancesCounter = 0;
        this.maxInstancesPerClass = max;
        this.warmUp = warmUp;
        this.testRun = testRun;
        for (int i = 0; i < allClasses.length; i++) {
            RefClass proxy = allClasses[i];
            MofClass metaClass = (MofClass) proxy.refMetaObject ();
            if (!metaClass.isAbstract ()) {
                int count = (warmUp ? 1 : 1 + random.nextInt (maxInstancesPerClass));
                for (int x = 0; x < count; x++)
                    generateInstance (metaClass);
            }
        }
    }

    public void modifyObjects (long randSeed, int max, boolean warmUp, boolean testRun) {
        random.setSeed (randSeed);
        instancesCounter = 0;
        this.maxInstancesPerClass = max;
        this.warmUp = warmUp;
        this.testRun = testRun;
        for (int i = 0; i < allClasses.length; i++) {
            RefClass proxy = allClasses[i];
            MofClass metaClass = (MofClass) proxy.refMetaObject ();
            if (!metaClass.isAbstract ()) {
                int count = (warmUp ? 1 : 1 + random.nextInt (maxInstancesPerClass));
                for (int x = 0; x < count; x++)
                    modifyInstance (metaClass);
            }
        }
    }
    
    public void prepareAssociationEnds() {
        for (int i = 0; i < allAssociations.length; i++)
            elementsCache.associationEndInstances ((Association)allAssociations[i].refMetaObject());
    }

    
    /**
     * Generates random assiciations in given extent.
     *
     * @param target extent
     * @param randSeed value to initialize random generator with
     * @param max maximal number of instances that should be generated per one class proxy
     */
    public void generateAssociations (long randSeed, int max, boolean warmUp, boolean testRun) {
        random.setSeed (randSeed);
        instancesCounter = 0;
        linksCounter = 0;
        this.maxInstancesPerClass = max;
        this.warmUp = warmUp;
        this.testRun = testRun;
        for (int i = 0; i < allAssociations.length; i++) {
            RefAssociation assoc = allAssociations[i];
            Association metaAssoc = (Association) assoc.refMetaObject ();
            if (!metaAssoc.isAbstract () && !metaAssoc.isDerived ()) {
                int count = (warmUp ? 1 : 1 + random.nextInt (maxInstancesPerClass));
                for (int x = 0; x < count; x++)
                    generateAssociation (metaAssoc);
            }
        }
    }

    public void findAllOfClass(int idx) {
        allClasses[idx].refAllOfClass();
    }
    
    public int iterateAllOfClass(int idx) {
        int i = 0;
        for (Iterator it = allClasses[idx].refAllOfClass().iterator(); it.hasNext(); it.next())
            i++;
        return i;
    }
    
    public int queryAssociations(long randSeed, int max) {
        random.setSeed(randSeed);
        othersCounter = 0;
        int totalNumOfIter = 0;
        for (int i = 0; i < allAssociations.length; i++) {
            RefAssociation assoc = allAssociations[i];
            if (((Association)assoc.refMetaObject()).isDerived())
                continue;
            int numOfIter = random.nextInt(max);
            for (int j = 0; j < numOfIter; j++) {
                int end = random.nextInt(2);
                RefObject[] inst = (RefObject[])elementsCache.associationEndInstances((Association)assoc.refMetaObject()).get(end);
                if (inst.length == 0)
                    continue;
                AssociationEnd aEnd = (AssociationEnd)elementsCache.associationEnds((Association)assoc.refMetaObject()).get(end);
                if (!aEnd.otherEnd().isNavigable())
                    continue;
                Collection others = assoc.refQuery(aEnd, inst[random.nextInt(inst.length)]);
                totalNumOfIter++;
                for (Iterator it = others.iterator(); it.hasNext(); it.next())
                    othersCounter++;
            }
        }
        return totalNumOfIter;
    }
    
    public int prepareObjectsToDelete(long randSeed, int max) {
        random.setSeed(randSeed);
        toDelete = new ArrayList();
        HashSet composites = new HashSet();
        for (int i = 0; i < allClasses.length; i++) {
            Collection col = allClasses[i].refAllOfClass(); 
            for (Iterator it = col.iterator(); it.hasNext();) {
                RefObject next = (RefObject)it.next();
                RefFeatured composite = next.refOutermostComposite();
                if ((random.nextInt(col.size()) < max) && (!composites.contains(composite))) {
                    toDelete.add(next);
                    composites.add(composite);
                }
            }
        }
        return toDelete.size();
    }
    
    public void deleteObjects() {
        for (int i = 0; i < toDelete.size(); i++) {
            RefObject obj = (RefObject)toDelete.get(i);
            obj.refDelete();
        }
    }

    public int getInstancesCounter() {
        return instancesCounter;
    }
    
    public int getLinksCounter() {
        return linksCounter;
    }

    public int getOthersCounter() {
        return othersCounter;
    }
    
    public int getNumberOfClasses() {
        return allClasses.length;
    }
    
    // private methods .........................................................
    
    private RefStruct generateStructure (StructureType type) {
        List fields = elementsCache.structureFields (type);
        List values = new LinkedList ();
        Iterator iter = fields.iterator ();
        while (iter.hasNext ()) {
            StructureField field = (StructureField) iter.next ();
            Classifier fieldType = field.getType ();
            values.add (generateValue (fieldType));
        }        
        RefBaseObject proxy = elementsCache.findProxy (type);
        if (testRun)
            return null;
        if (proxy instanceof RefClass)
            return ((RefClass) proxy).refCreateStruct (type, values);
        else
            return ((RefPackage) proxy).refCreateStruct (type, values);
    }
    
    private RefEnum generateEnumeration (EnumerationType type) {
        List labels = type.getLabels ();
        int index = random.nextInt (labels.size ());
        RefBaseObject proxy = elementsCache.findProxy (type);
        if (testRun)
            return null;
        if (proxy instanceof RefClass)
            return ((RefClass) proxy).refGetEnum (type, (String) labels.get (index));
        else
            return ((RefPackage) proxy).refGetEnum (type, (String) labels.get (index));
    }
    
    private Object generatePrimitive (PrimitiveType type) {
        String typeName = type.getName ();
        if (XmiConstants.BOOLEAN_TYPE.equals (typeName))
            return random.nextBoolean () ? Boolean.TRUE : Boolean.FALSE;
        if (XmiConstants.DOUBLE_TYPE.equals (typeName))
            return new Double (random.nextDouble ());
        if (XmiConstants.FLOAT_TYPE.equals (typeName))
            return new Float (random.nextFloat ());
        if (XmiConstants.INTEGER_TYPE.equals (typeName))
            return new Integer (random.nextInt ());
        if (XmiConstants.LONG_TYPE.equals (typeName))
            return new Long (random.nextLong ());
        if (XmiConstants.STRING_TYPE.equals (typeName))
            return generateString ();
        throw new DebugException ("Unknown type: " + typeName);
    }
    
    private String generateString () {
        int length = random.nextInt (20);
        byte [] chars = new byte [length];        
        random.nextBytes (chars);
        for (int x = 0; x < length; x++)
            chars [x] = (byte) ('a' + Math.abs (chars [x] % 24)); // convert to alpha characters only
        return new String (chars);
    }
    
    private Object generateValue (Classifier type) {
        while (type instanceof AliasType)
            type = ((AliasType) type).getType ();
        if (type instanceof MofClass)
            return generateInstance ((MofClass) type);
        if (type instanceof PrimitiveType)
            return generatePrimitive ((PrimitiveType) type);
        if (type instanceof StructureType)
            return generateStructure ((StructureType) type);
        if (type instanceof EnumerationType)
            return generateEnumeration ((EnumerationType) type);
        throw new DebugException ("Unknown or unsupported type: " + type.getName ());
    }
    
    private RefObject generateInstance (MofClass mofClass) {
        RefPackage refPackage = (RefPackage) elementsCache.findProxy (mofClass);
        RefClass proxy = refPackage.refClass (mofClass);
        List args = new LinkedList ();
        Iterator iter = elementsCache.instanceAttributes (mofClass).iterator ();
        while (iter.hasNext ()) {
            Attribute attr = (Attribute) iter.next ();
            args.add (generateAttributeValue (attr));
        } // while
        instancesCounter++;
        if (testRun)
            return null;
        return proxy.refCreateInstance (args);
    }
    
    private RefObject modifyInstance(MofClass mofClass) {
        RefObject inst = findInstance(elementsCache.classInstances(mofClass));
        List list = elementsCache.instanceAttributes (mofClass);
        if (list.size() > 0) {
            int idx = random.nextInt(list.size());
            Attribute attr = (Attribute) list.get (idx);
            if (attr.isChangeable()) {
                Object value = generateAttributeValue (attr);
                if (!testRun)
                    inst.refSetValue(attr, value);
                instancesCounter++;
            }
        }
        return inst;
    }

    private RefObject findInstance (RefObject[] objs) {
        if (objs == null || objs.length == 0)
            return null;
        return objs[random.nextInt(objs.length)];
    }
    
    private Object generateAttributeValue (Attribute attribute) {
        MultiplicityType multType = attribute.getMultiplicity ();
        Classifier type = attribute.getType ();
        while (type instanceof AliasType)
            type = ((AliasType) type).getType ();
        // check, if type is not an abstract class, if so find a suitable descendant
        if ((type instanceof MofClass) && ((MofClass) type).isAbstract ())
            type = findSubtype ((MofClass) type);
        int upper = multType.getUpper ();        
        int lower = multType.getLower ();
        boolean isMultivalued = upper != 1;
        
        if ((lower == 0) && random.nextBoolean ()) {
            // if the attribute is optional, generate no value with 50% probality
            return isMultivalued ? new LinkedList () : null;
        }
        
        if (!isMultivalued)
            return generateValue (type); // [PENDING] it would be better to generate instances of 
                                         // various subtypes of a given type ...
        if (upper == -1) upper = lower + 3;
        int count = lower + random.nextInt (upper - lower + 2);
        // we limit the nuber of generated values to be between 1 and 10
        if (count == 0) count = 1;
        if (count > 10) count = 10;
        List values = new LinkedList ();
        for (int x = 0; x < count; x++)
            values.add (generateValue (type));
        return values;
    }
    
    private MofClass findSubtype (MofClass mofClass) {
        List list = elementsCache.nonAbstractSubtypes (mofClass);
        if ((list == null) || (list.size () == 0))
            throw new DebugException ("Cannot find a non-abstract subtype: " + mofClass.getName ());
        int index = random.nextInt (list.size ());
        return (MofClass) list.get (index);
    }        
    
    private void generateAssociation (Association mofAssoc) {
        RefPackage refPackage = (RefPackage) elementsCache.findProxy (mofAssoc);
        RefAssociation proxy = refPackage.refAssociation (mofAssoc);
        List ends = elementsCache.associationEnds (mofAssoc);
        List endInstances = elementsCache.associationEndInstances (mofAssoc);
        AssociationEnd aEnd = (AssociationEnd) ends.get (0);
        RefObject obj1 = null;
        if (aEnd.otherEnd().getAggregation() == AggregationKindEnum.COMPOSITE) {
            Classifier type = aEnd.getType ();
            while (type instanceof AliasType)
                type = ((AliasType) type).getType ();
            // check, if type is not an abstract class, if so find a suitable descendant
            if ((type instanceof MofClass) && ((MofClass) type).isAbstract ())
                type = findSubtype ((MofClass) type);
            obj1 = generateInstance((MofClass)type);
        }
        else {
            obj1 = findInstance((RefObject[])endInstances.get(0));
            if (obj1 == null)
                return;
            int bound = aEnd.getMultiplicity().getUpper();
            if (bound != -1 && proxy.refQuery(aEnd, obj1).size() >= bound)
                return;
        }
        aEnd = (AssociationEnd) ends.get (1);
        RefObject obj2 = null;
        if (aEnd.otherEnd().getAggregation() == AggregationKindEnum.COMPOSITE) {
            Classifier type = aEnd.getType ();
            while (type instanceof AliasType)
                type = ((AliasType) type).getType ();
            // check, if type is not an abstract class, if so find a suitable descendant
            if ((type instanceof MofClass) && ((MofClass) type).isAbstract ())
                type = findSubtype ((MofClass) type);
            obj2 = generateInstance((MofClass)type);
        }
        else {
            obj2 = findInstance((RefObject[])endInstances.get(1));
            if (obj2 == null)
                return;
            int bound = aEnd.getMultiplicity().getUpper();
            if (bound != -1 && proxy.refQuery(aEnd, obj2).size() >= bound)
                return;
        }
        if (testRun)
            return;
        proxy.refAddLink (obj1, obj2);
        linksCounter++;
    }

    private void prepareAllClasses () {
        trackedPackages.clear();
        Collection col = findAllClasses (target);
        allClasses = (RefClass[]) col.toArray(new RefClass[col.size()]);
    }
    
    private Collection findAllClasses (RefPackage target) {
        if (trackedPackages.contains (target))
            return null;
        trackedPackages.add (target);
        Collection clss = target.refAllClasses ();
        Iterator iter = target.refAllPackages ().iterator ();
        while (iter.hasNext ())
            clss.addAll(findAllClasses ((RefPackage) iter.next ()));
        return clss;
    }

    private void prepareAllAssociations () {
        trackedPackages.clear();
        Collection col = findAllAssociations (target);
        allAssociations = (RefAssociation[]) col.toArray(new RefAssociation[col.size()]);
    }
    
    private Collection findAllAssociations (RefPackage target) {
        if (trackedPackages.contains (target))
            return null;
        trackedPackages.add (target);
        Collection assocs = target.refAllAssociations ();
        Iterator iter = target.refAllPackages ().iterator ();
        while (iter.hasNext ())
            assocs.addAll(findAllAssociations ((RefPackage) iter.next ()));
        return assocs;
    }

}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.