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 RandomDataGenerator extends Object {
    
    // variables ................................................................
    
    // extent in which random data are generated
    private RefPackage target;
    // maximal number of instances that should be generated per one class proxy
    private int maxInstancesPerClass;
    // used random generator
    private Random random = new Random ();
        
    protected ElementsCache elementsCache;
    
    // stores the number of created instaces
    private int instancesCounter = 0;
    // stores all currently processed packages (see generateUniformly() method)
    private HashMap trackedPackages = new HashMap ();
    
    // init .....................................................................
    
    public RandomDataGenerator () {
    }
    
    public RandomDataGenerator (RefPackage pkg) {
        elementsCache = new ElementsCache (pkg);
    }
    
    // methods ..................................................................
    
    /**
     * Generates random data 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 generate (RefPackage target, long randSeed, int max) {
        random.setSeed (randSeed);
        this.target = target;
        this.maxInstancesPerClass = max;
        elementsCache = new ElementsCache (target);
        generateUniformly (target);
    }
    
    public void generateUniformly (RefPackage target) {
        if (trackedPackages.get (target) != null)
            return;
        trackedPackages.put (target, target);
        System.out.println("package: " + target);
        Iterator iter = target.refAllClasses ().iterator ();
        while (iter.hasNext ()) {
            RefClass proxy = (RefClass) iter.next ();
            MofClass metaClass = (MofClass) proxy.refMetaObject ();
            System.out.println ("class: " + metaClass.getName ());
            if (!metaClass.isAbstract ()) {
                int count = 1 + random.nextInt (maxInstancesPerClass);
                for (int x = 0; x < count; x++)
                    generateInstance (metaClass);
            } // if
        } // while
        iter = target.refAllAssociations ().iterator ();
        while (iter.hasNext ()) {
            RefAssociation proxy = (RefAssociation) iter.next ();
            int count = 1 + random.nextInt (2 * maxInstancesPerClass / 3);                
            generateAssociation (proxy, count);
        } // while
        iter = target.refAllPackages ().iterator ();
        while (iter.hasNext ())
            generateUniformly ((RefPackage) iter.next ());
    }
    
    public 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 (proxy instanceof RefClass)
            return ((RefClass) proxy).refCreateStruct (type, values);
        else
            return ((RefPackage) proxy).refCreateStruct (type, values);
    }
    
    public Collection generateCollection (CollectionType colType) {
        Classifier type = colType.getType ();
        MultiplicityType mul = colType.getMultiplicity ();
        int upper = mul.getUpper ();
        int lower = mul.getLower ();
        int num;        
        if (lower > 0)
            num = lower + random.nextInt (5);
        else
            num = 3 + random.nextInt (5);        
        if ((upper > 0) && (num > upper))
            num = upper;
        List values = new LinkedList ();
        for (int x = 0; x < num; x++)
            values.add (generateValue (type));
        return values;
    }
    
    public RefEnum generateEnumeration (EnumerationType type) {
        List labels = type.getLabels ();
        int index = random.nextInt (labels.size ());
        RefBaseObject proxy = elementsCache.findProxy (type);        
        if (proxy instanceof RefClass)
            return ((RefClass) proxy).refGetEnum (type, (String) labels.get (index));
        else
            return ((RefPackage) proxy).refGetEnum (type, (String) labels.get (index));
    }
    
    public 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);
    }
    
    public 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);
    }
    
    public 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);
        if (type instanceof CollectionType)
            return generateCollection ((CollectionType) type);
        throw new DebugException ("Unknown or unsupported type: " + type.getName ());
    }
    
    public 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++;
        return proxy.refCreateInstance (args);
    }
    
    public 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;
        
        if (multType.isUnique ())
            count = 1;
        
        List values = new LinkedList ();
        for (int x = 0; x < count; x++)
            values.add (generateValue (type));
        return values;
    }

    public void generateAssociation (RefAssociation proxy, int count) {                
        Association assoc = (Association) proxy.refMetaObject ();
        if (assoc.isDerived ())
            return;
        
        AssociationEnd endA = null, endB = null;
        Iterator content = assoc.getContents ().iterator ();
        while (content.hasNext ()) {
            Object elem = content.next ();
            if (elem instanceof AssociationEnd) {
                if (endA == null)
                    endA = (AssociationEnd) elem;
                else {
                    endB = (AssociationEnd) elem;
                    break;
                } // if
            } // if
        } // while

        MofClass typeA = findSubtype ((MofClass) endA.getType ());
        MofClass typeB = findSubtype ((MofClass) endB.getType ());

        if ((typeA == null) || (typeB == null))
            return;

        MultiplicityType multA = endA.getMultiplicity ();
        MultiplicityType multB = endB.getMultiplicity ();
        int lowerA = Math.max (1, multA.getLower ());
        int lowerB = Math.max (1, multB.getLower ());
        int upperA = lowerA + 4;
        int upperB = lowerB + 4;
        if (multA.getUpper () != -1)
            upperA = Math.min (upperA, multA.getUpper ());
        if (multB.getUpper () != -1)
            upperB = Math.min (upperB, multB.getUpper ());

        do {
            int x, y;
            int countA = lowerA + ((upperA - lowerA > 0) ? random.nextInt (upperA - lowerA) : 0);
            int countB = lowerB + ((upperB - lowerB > 0) ? random.nextInt (upperB - lowerB) : 0);
            RefObject [] objA = new RefObject [countA];
            RefObject [] objB = new RefObject [countB];
            for (x = 0; x < countA; x++) {
                objA [x] = generateInstance (typeA);
            }
            for (x = 0; x < countB; x++) {
                objB [x] = generateInstance (typeB);
            }
            for (x = 0; x < countA; x++)
                for (y = 0; y < countB; y++)
                    proxy.refAddLink (objA[x], objB[y]);
        } while (--count > 0);

    }
    
    public MofClass findSubtype (MofClass mofClass) {
        if (!mofClass.isAbstract())
            return mofClass;
        List list = elementsCache.nonAbstractSubtypes (mofClass);
        if ((list == null) || (list.size () == 0))
            return null;            
        int index = random.nextInt (list.size ());
        return (MofClass) list.get (index);
    }        
    
}
... 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.