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.lib.jmi.mapping;

import org.netbeans.lib.jmi.util.TagProvider;
import javax.jmi.model.*;
import javax.jmi.reflect.*;
import java.io.IOException;
import java.util.*;

/**
 * Generates java interfaces for specified meta objects or whole meta model.
 *
 * @author  Dusan Balek, Martin Matula
 * @version 0.1
 */
public abstract class GenericMapper {
    protected static String PACKAGE_POSTFIX = "Package"; //NOI18N
    protected static String CLASS_POSTFIX = "Class"; //NOI18N
    protected static String ENUM_POSTFIX = "Enum"; //NOI18N
    
    // name of exception used as an ancestor for all the mapped exceptions
    protected static final String DT_EXCEPTION = "javax.jmi.reflect.RefException"; //NOI18N
    // name of package used as an ancestor for all the mapped packages
    protected static final String DT_PACKAGE = "javax.jmi.reflect.RefPackage"; //NOI18N
    // name of association used as an ancestor for all the mapped associations
    protected static final String DT_ASSOCIATION = "javax.jmi.reflect.RefAssociation"; //NOI18N
    // name of class proxy used as an ancestor for all the mapped calss proxies
    protected static final String DT_CLASS = "javax.jmi.reflect.RefClass"; //NOI18N
    // name of class instance used as an ancestor for all the mapped class instances
    protected static final String DT_INSTANCE = "javax.jmi.reflect.RefObject"; //NOI18N
    // name of structure used as an ancestor for all the mapped strucutres
    protected static final String DT_STRUCTURE = "javax.jmi.reflect.RefStruct"; //NOI18N
    // name of enumeration used as an ancestor for all the mapped enumerations
    protected static final String DT_ENUMERATION = "javax.jmi.reflect.RefEnum"; //NOI18N
    // name of java type used to represent multivalued unordered values
    protected static final String DT_MULTIVALUED = "java.util.Collection"; //NOI18N
    // name of java type used to represent multivalued ordered values
    protected static final String DT_ORDERED = "java.util.List"; //NOI18N
    // name of java type uset to represent values of type ANY
    protected static final String DT_ANY = "java.lang.Object"; //NOI18N
    
    protected final TagProvider tagProvider = new TagProvider();
    
    // used for storing already visited object so that the interfaces
    // are not generated twice for them
    protected final Set visited = new HashSet();

    // conversion table between object type names and primitive type names
    protected static final HashMap objectToPrimitive = new HashMap(7);
    static {
        objectToPrimitive.put("java.lang.Short", "short"); //NOI18N
        objectToPrimitive.put("java.lang.Integer", "int"); //NOI18N
        objectToPrimitive.put("java.lang.Float", "float"); //NOI18N
        objectToPrimitive.put("java.lang.Double", "double"); //NOI18N
        objectToPrimitive.put("java.lang.Boolean", "boolean"); //NOI18N
        objectToPrimitive.put("java.lang.Character", "char"); //NOI18N
        objectToPrimitive.put("java.lang.Long", "long"); //NOI18N
    }
    
    // helper function for converting first character of the string to upper case
    protected static String firstUpper(String text) {
        if (text == null) return null;
        if (text.length() < 2) return text.toUpperCase();
        return text.substring(0, 1).toUpperCase() + text.substring(1);
    }

    // helper function for converting first character of the string to lower case
    protected static String firstLower(String text) {
        if (text == null) return null;
        if (text.length() < 2) return text.toLowerCase();
        return text.substring(0, 1).toLowerCase() + text.substring(1);
    }

    // helper function for removing underscore characters from a structure member name
    protected static String removeUnderscores(String text) {
        StringBuffer result = new StringBuffer(text.length());
        int pos = 0; 
        int oldPos = 0;
        String firstChar;

        while (oldPos <= text.length()) {
            if ((pos = text.indexOf('_', oldPos)) == -1) {
                pos = text.length() + 1;
            }
            if (pos - oldPos > 1) {
                firstChar = text.substring(oldPos, oldPos + 1);
                // convert the letter following the "_" to uppercase it
                // in case it is not the first character
                if (oldPos > 0) {
                    firstChar = firstChar.toUpperCase();
                }
                // and append it
                result.append(firstChar);
                // append the rest of the string to the next "_"
                if (pos > text.length()) {
                    result.append(text.substring(oldPos + 1));
                } else {
                    result.append(text.substring(oldPos + 1, pos));
                }
            }
            oldPos = pos + 1;
        }

        return result.toString();
    }
    
    // method for parsing the package name
    private static List parseDots(String packageName) {
        int position;
        String name = packageName;
        ArrayList result = new ArrayList();

        while ((position = name.indexOf('.')) > 0) {
            result.add(name.substring(0, position));
            name = name.substring(position + 1);
        }

        if (position != 0) {
            result.add(name);
        }

        return result;
    }

    // resolves datatype of typed element with aliases support
    protected Classifier getAttrType(TypedElement attr) {
        Classifier curType = attr.getType();
        Classifier attrType = (Classifier) aliasesCache.get(curType);

        if (attrType == null) {
            attrType = curType;
            if (curType instanceof AliasType) {
                attrType = getAttrType((TypedElement) curType);
            }
            // put type mapping into cache
            aliasesCache.put(curType, attrType);
        }

        return attrType;
    }

    // returns correct type name for attribute (depending on the multiplicity type)
    protected String getTypeName(Attribute attr) {
        MultiplicityType mp = attr.getMultiplicity();
        
        if (mp.getUpper() > 1 || mp.getUpper() == -1) {
            return (mp.isOrdered() ? DT_ORDERED : DT_MULTIVALUED);
        } else if (mp.getLower() < 1) {
            return getTypeName(getAttrType(attr));
        } else {
            return getTypeName2(attr);
        }
    }
    
    protected String getTypeName2(TypedElement te) {
        return getPrimitiveName(getTypeName(getAttrType(te)));
    }
    
    // returns correct type name for parameter (depending on the multiplicity type)
    protected String getTypeName(Parameter prm) {
        MultiplicityType mp = prm.getMultiplicity();
        
        if (mp.getUpper() > 1 || mp.getUpper() == -1) {
            return (mp.isOrdered() ? DT_ORDERED : DT_MULTIVALUED);
        } else if (mp.getLower() < 1) {
            return getTypeName(getAttrType(prm));
        } else {
            return getTypeName2(prm);
        }
    }
    
    // resolves datatype name
    protected String getTypeName(Classifier type) {
        String result = (String) typeNameCache.get(type);

        if (result == null) {
            result = tagProvider.getDataTypeName(type);
            typeNameCache.put(type, result);
        }

        return result;
    }

    // converts object type name to primitive type name
    protected String getPrimitiveName(String typeName) {
        String name = (String) objectToPrimitive.get(typeName);
        return name == null ? typeName : name;
    }
    
    // returns true if the attribute can be mapped to primitive type
    protected static boolean canBePrimitive(String typeName) {
        return (objectToPrimitive.get(typeName) != null);
    }

    // cache for datatype aliases
    protected final Hashtable aliasesCache = new Hashtable(100);
    // cache for type names
    protected final Hashtable typeNameCache = new Hashtable(100);
    
    // template methods -----------------------------------------------------------------------------------------------------
    
    // generates instance interface for a given class
    protected abstract void classInstanceTemplate(javax.jmi.model.MofClass objClass) throws IOException;
    // generates proxy interface for a given class
    protected abstract void classProxyTemplate(javax.jmi.model.MofClass objClass) throws IOException;

    // generates interface for a given association
    protected abstract void associationTemplate(Association objAssociation) throws IOException;
    
    protected abstract void packageTemplate(MofPackage objPackage) throws IOException;
    
    // generates class for an exception
    protected abstract void exceptionTemplate(MofException objException) throws IOException;
    
    // generates interface for an enumeration
    protected abstract void enumerationInterfaceTemplate(EnumerationType objEnumeration) throws IOException;
    // generates class for an enumeration
    protected abstract void enumerationClassTemplate(EnumerationType objEnumeration) throws IOException;

    // generates interface for a structure
    protected abstract void structureTemplate(StructureType objStructure) throws IOException;

    // public ---------------------------------------------------------------------------------------------------------------

    public GenericMapper() { }
    
    // stream handling ------------------------------------------------------------------------------------------------------
    
    /** Called when the mapper is about to start writing a new interface or class.
     *  The subclass should open the output stream or whatever it is going to write to.
     *  @return true if the stream was created;
     *          false if this interface/class should be skipped.
     */
    protected abstract boolean createStream(List pkg, String filename) throws IOException;
    /** Called to close the output stream opened by {@link #closeStream}.
     *  closeStream is called once for every time that createStream returns
     *  true.
     */
    protected abstract void closeStream() throws IOException;
    
    private boolean streamOpen = false;
    private boolean switchStream(ModelElement me, String suffix) throws IOException {
        if (streamOpen) {
            streamOpen = false;
            closeStream();
        }
        streamOpen = createStream(parseDots(tagProvider.getTypePrefix(me)),
            tagProvider.getSubstName(me) + suffix);
        return streamOpen;
    }

    // implementation of Visotor interface ----------------------------------------------------------------------------------

    /** 

* The implementation does nothing because there is nothing to map on RefAssociation. *

* @param refAssociation Reference to a RefAssociation object. */ public void visitRefAssociation(RefAssociation refAssociation) throws IOException { // Logger.getDefault().log("generating association proxy..."); visitRefObject(refAssociation.refMetaObject()); } /**

* Generates the interfaces for all the instances created by the passed class proxy. *

* @param refClass Reference to a class proxy. */ public void visitRefClass(RefClass refClass) throws IOException { // Logger.getDefault().log("generating class proxy..."); if (refClass.refImmediatePackage() instanceof ModelPackage) { for (Iterator it = refClass.refAllOfClass().iterator(); it.hasNext();) { visitRefObject((RefObject) it.next()); } } } /**

* Generates interfaces for the passed object instance. *

* @param refObject Reference to a class instance. */ public void visitRefObject(RefObject refObject) throws IOException { if (visited.contains(refObject) || !(refObject instanceof Namespace)) { return; } Namespace outermost = (Namespace) refObject; for (;;) { Namespace container = outermost.getContainer(); if (container == null) break; outermost = container; } if (!(outermost instanceof MofPackage)) { return; } boolean ignoreLifecycle = false; String ignoreLifecycleString = tagProvider.getTagValue(outermost, TagProvider.TAGID_IGNORE_LIFECYCLE); if (ignoreLifecycleString != null) { if (ignoreLifecycleString.equals("true")) //NOI18N ignoreLifecycle = true; // else if (!ignoreLifecycle.equals("false")) ... this is against the JMI spec } try { if (refObject instanceof Association) { // Logger.getDefault().log("generating association... " + ((ModelElement) refObject).getName()); if (!ignoreLifecycle && switchStream((Association)refObject, "")) //NOI18N associationTemplate((Association)refObject); } else if (refObject instanceof MofClass || refObject instanceof MofPackage) { GeneralizableElement elm = (GeneralizableElement) refObject; visited.add(elm); for (Iterator it = elm.getSupertypes().iterator(); it.hasNext();) { visitRefObject((RefObject) it.next()); } Collection contents = elm.getContents(); for (Iterator it = contents.iterator(); it.hasNext();) { visitRefObject((RefObject) it.next()); } if (elm instanceof MofPackage) { // Logger.getDefault().log("generating package... " + ((ModelElement) refObject).getName()); if (!ignoreLifecycle && switchStream(elm, PACKAGE_POSTFIX)) packageTemplate((MofPackage) elm); } else { // Logger.getDefault().log("generating class... " + ((ModelElement) refObject).getName()); if (switchStream(elm, "")) //NOI18N classInstanceTemplate((MofClass) elm); if (!ignoreLifecycle && switchStream(elm, CLASS_POSTFIX)) classProxyTemplate((MofClass) elm); } } else if (refObject instanceof EnumerationType) { // Logger.getDefault().log("generating enumeration... " + ((ModelElement) refObject).getName()); final EnumerationType et = (EnumerationType) refObject; if (switchStream(et, "")) //NOI18N enumerationInterfaceTemplate(et); if (switchStream(et, ENUM_POSTFIX)) enumerationClassTemplate(et); } else if (refObject instanceof StructureType) { // Logger.getDefault().log("generating structure... " + ((ModelElement) refObject).getName()); if (switchStream((StructureType)refObject, "")) //NOI18N structureTemplate((StructureType)refObject); } else if (refObject instanceof MofException) { // Logger.getDefault().log("generating exception... " + ((ModelElement) refObject).getName()); if (switchStream((MofException)refObject, "")) //NOI18N exceptionTemplate((MofException)refObject); } else { // Logger.getDefault().log("nothing will be generated for type: " + refObject.getClass()); } } finally { if (streamOpen) { streamOpen = false; closeStream(); } } } /**

* Generates interfaces for all objects created within the passed package proxy *

* @param refPackage Reference to a package proxy. */ public void visitRefPackage(RefPackage refPackage) throws IOException { //Logger.getDefault().log("generating package proxy..."); if (refPackage instanceof ModelPackage) { ModelPackage pkg = (ModelPackage) refPackage; ModelElement element; for (Iterator it = pkg.getMofPackage().refAllOfClass().iterator(); it.hasNext();) { element = (ModelElement) it.next(); if (element.getContainer() == null) { visitRefObject(element); } } } } public void visitRefBaseObject(RefBaseObject object) throws IOException { if (object instanceof RefPackage) { visitRefPackage((RefPackage) object); } else if (object instanceof RefObject) { visitRefObject((RefObject) object); } else if (object instanceof RefAssociation) { visitRefAssociation((RefAssociation) object); } else if (object instanceof RefClass) { visitRefClass((RefClass) object); } } }
... 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.