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

com.draagon.meta.loader.model.MetaModelParser Maven / Gradle / Ivy

package com.draagon.meta.loader.model;

import com.draagon.meta.*;
import com.draagon.meta.loader.MetaDataLoader;
import com.draagon.meta.loader.types.*;
import com.draagon.meta.loader.parser.ParserBase;
import com.draagon.meta.util.MetaDataUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.List;

public abstract class MetaModelParser extends ParserBase {

    private Log log = LogFactory.getLog( this.getClass() );

    private String defaultPackageName = null;

    protected MetaModelParser(MetaModelLoader modelLoader, String sourceName) {
        super(modelLoader, sourceName);
    }

    /* Load MetaDataModel Stream */
    public abstract void loadAndMerge( I intoLoader, S source );

    /** Merge the loaded MetaDataModel into the specified MetaDataLoader */
    protected  void mergeMetaDataModel( I intoLoader, M model ) {

        TSC typesConfig = intoLoader.getTypesConfig();
        if ( typesConfig == null ) throw new IllegalStateException( "MetaDataLoader did not have a TypesConfig set, loader=["+intoLoader+"]");

        // Get the TypeConfig for the root model (throws exception)
        TypeConfig tc = getTypeConfig( typesConfig, model );

        // Set The default Package from the root MetaModel
        String defPkg = getDefaultPackageName( tc, model );

        // Begin merging the MetaModels into the Laoder
        mergeMetaData( intoLoader, defPkg, typesConfig, model );
    }

    /** Set default package name */
    protected  String getDefaultPackageName( T typeConfig, M model ) {

        String defPkg = model.getPackage();
        if ( defPkg == null ) defPkg = "";
        return defPkg;
    }

    /** Merge the MetaModels into the parent MetaData */
    protected  void mergeMetaData(
            MetaData parent, String pkgDef, TSC typesConfig, M model) {

        List children = (List) model.getChildren();
        if ( children == null ) return;

        for ( M child : children ) {

            // Attempt to get TypeConfig and return null if no type was found
            TypeConfig tc = getTypeConfig( typesConfig, child );

            // Create or Overload MetaData from the Model
            MetaData merge = createOrOverloadMetaData(parent, pkgDef, tc, child );

            // Merge additional records from the Model
            mergeAdditionalModelData( parent, merge, tc, child );

            // Merge child records
            mergeMetaData( merge, pkgDef, typesConfig, child );
        }
    }

    protected  void mergeAdditionalModelData(
            MetaData parent, MetaData merge, TypeConfig tc, M model) {

        // Merge the Value for MetaDataValueHandlers like MetaAttribute
        if ( merge instanceof MetaDataValueHandler && model.getValue() != null ) {
            ((MetaDataValueHandler)merge).setValueAsObject(model.getValue());
        }
    }

    protected  MetaData createOrOverloadMetaData(
            MetaData parent, String pkgDef, TypeConfig tc, M model) {

        String superName = getFullSuperName(parent, tc, pkgDef, model);

        // If the name is null, then try to set it
        String fullname = getFullname(parent, tc, pkgDef, model);

        // Create or Overload MetaData from Model with specified superName and fullname
        return createOrOverloadMetaDataWithName(parent, tc, model, superName, fullname);
    }

    protected  String getFullSuperName(
            MetaData parent, T tc, String pkgDef, M model) {

        if (model.getSuper() == null) return null;

        // If the parent is not the MetaDataLoader, then see if the parent package is different
        // and if so, use that to reference the superData
        String superPkgDef = pkgDef;
        if (!(parent instanceof MetaDataLoader)) {
            String p = MetaDataUtil.findPackageForMetaData(parent);
            if (!p.isEmpty()) { //&& !p.equals( pkgDef ))  {
                superPkgDef = p;
            }
        }

        // TODO:  Add support for pointing to sub children with . notation

        if (model.getSuper().contains(MetaDataLoader.PKG_SEPARATOR))
            return MetaDataUtil.expandPackageForMetaDataRef(superPkgDef, model.getSuper());
        else
            return superPkgDef + MetaDataLoader.PKG_SEPARATOR + model.getSuper();
    }

    protected  String getPackage(MetaData parent, String pkgDef, M model) {

        String pkg = model.getPackage();
        // NOTE:  Should it always be that you only fully qualify names when the parent
        // is the MetaDataLoader?
        if (pkg == null && parent instanceof MetaDataLoader)  {
            pkg = pkgDef;
        }
        if ( pkg == null ) pkg="";
        return pkg;
    }

    protected  String getFullname(
            MetaData parent, T tc, String pkgDef, M model ) {

        String pkg = getPackage(parent, pkgDef, model);

        String name = model.getName();
        if ( name == null ) {
            name = autoCreateNameFromTypeConfig(parent, tc, model);
        }
        if ( name == null ) {
            throw new InvalidValueException( "Name is null, cannot merge MetaDataModel ["+model+"]" );
        }
        return (pkg.isEmpty()?"":pkg + "::") + name;
    }

    protected  String autoCreateNameFromTypeConfig(
            MetaData parent, T tc, M model ) {

        String name = null;
        if ( tc.getDefaultName() != null ) {
            name = tc.getDefaultName();
        }
        else if ( tc.getDefaultNamePrefix() != null ) {

            int i = 0;

            // TODO: If auto named, then super could match, or we could match by subType
            for( MetaData md : parent.getChildrenOfType( tc.getName(), true )) {
                if ( md.getName().startsWith( tc.getDefaultNamePrefix() )) {
                    String n = md.getName().substring(tc.getDefaultNamePrefix().length());
                    try {
                        i = Integer.parseInt(n);
                    }
                    catch( NumberFormatException ex ) {
                        log.warn("Error parsing ["+n+"] on name ["+md.getName()+"] on autoname creation for model: " +model);
                    }
                }
            }
            name = tc.getDefaultNamePrefix()+(++i);
        }
        return name;
    }

    protected  MetaData createOrOverloadMetaDataWithName(
            MetaData parent, T tc, M model, String superName, String fullname) {

        MetaData merge = findExistingMetaData(parent, tc, fullname);

        if ( merge != null ) {
            merge = overloadedMetaData(tc, model, merge);
        }
        else {
            merge = createNewMetaData(parent, tc, model, superName, fullname, merge);
        }
        parent.addChild( merge );
        return merge;
    }

    protected  MetaData createNewMetaData(
            MetaData parent, T tc, M model, String superName, String fullname, MetaData merge) {

        String subType = null;

        // Get the superData && set the subType if null
        MetaData superData = null;
        if ( model.getSuper() != null ) {

            superData = getSuperData( parent, tc, model, superName );

            subType = superData.getSubTypeName();
            if ( model.getSubType() != null && !model.getSubType().equals(subType)) {
                throw new MetaDataException("SubType mismatch [" + model.getSubType() + "] != "+
                        "["+ merge.getSubTypeName()+"] on superData: " + superData );
            }
        }
        else {
            // Get the MetaData subType
            subType = getSubTypeName(tc, model);
        }

        SubTypeConfig stc = getSubTypeConfig(tc, model, subType);

        // Create the new MetaData
        merge = createNewMetaData(parent, tc, stc, fullname);

        // Set the SuperData if it exists
        if ( superData != null ) {
            validateSuperDataOnNew( merge, superData );
            merge.setSuperData( superData );
        }

        return merge;
    }

    protected  MetaData findExistingMetaData(MetaData parent, T tc, String fullname) {

        MetaData merge = null;
        try {
            merge = parent.getChildOfType( tc.getName(), fullname);
        } catch( MetaDataNotFoundException ignore ) {
            if ( log.isDebugEnabled() ) log.debug( "No child of type ["+tc.getName()+"] "+
                    " with name ["+fullname+"] on parent: "+parent);
        }
        return merge;
    }

    protected  MetaData overloadedMetaData(
            T tc,  M model, MetaData merge ) {

        // Get the superData && set the subType if null
        if ( model.getSuper() != null ) {
            throw new MetaDataException("Super reference [" + model.getSuper() + "] is not valid when "+
                    "overloading existing MetaData: " + merge );
        }

        // Verify the subType is the same as the existing
        else if ( model.getSubType() != null && !merge.getSubTypeName().equals(model.getSubType())) {
            throw new MetaDataException("SubType mismatch [" + model.getSubType() + "] != "+
                    "["+ merge.getSubTypeName()+"] attempting to overloaded existing " +
                    " metadata: " + merge );
        }

        // Overload the existing MetaData
        merge = merge.overload();
        return merge;
    }

    protected  T getTypeConfig( TSC tsc, M model ) {

        String typeName = model.getType();
        if ( typeName != null ) {
            for (TypeConfig tc : tsc.getTypes()) {
                if (typeName.equals(tc.getName())) return (T) tc;
            }
        }
        throw new InvalidValueException("Type [" + typeName + "] did not exist in TypesConfig, " +
                "cannot parse model: " + model);
    }

    protected  String getSubTypeName( T tc, M model ) {

        String subType = model.getSubType();
        if ( subType == null && tc.getDefaultSubType() != null ) {
            subType = tc.getDefaultSubType();
        }
        return subType;
    }

    protected  SubTypeConfig getSubTypeConfig(
            T tc, M model, String subType) {

        SubTypeConfig stc = null;

        if ( subType != null && tc.getSubTypes() != null ) {
            for ( SubTypeConfig st : tc.getSubTypes() ) {
                if ( st.getName().equals(subType)) {
                    stc = st;
                    break;
                }
            }
        }

        // Error if no subType was specified and there was no default
        if ( stc == null ) {
            throw new InvalidValueException( "Type ["+tc.getName()+"] with SubType ["+subType+"] did not exist "+
                    "in TypesConfig, cannot merge MetaDataModel: "+model );
        }
        return stc;
    }

    protected  MetaData createNewMetaData(
            MetaData parent, TC tc, T stc, String fullname) {
        MetaData merge;
        Class clazz = stc.getMetaDataClass();
        merge = (MetaData) parent.newInstanceFromClass( clazz, tc.getName(), stc.getName(), fullname );
        return merge;
    }

    protected void validateSuperDataOnNew(MetaData merge, MetaData superData ) {

        // TODO: Ensure the new superData has the same underlying superData overloads
        if (merge.getSuperData() != null && !merge.getSuperData().isSameTypeSubType(superData)) {
            throw new MetaDataException( "Specified superData subType mismatch "+
                    "["+superData.getSubTypeName()+"] != ["+merge.getSubTypeName()+"] on created metadata: "+merge );
        }
    }

    protected  MetaData getSuperData(
            MetaData parent, T tc, M model, String superName ) {

        MetaData superData;
        try {
            MetaDataLoader loader = parent.getLoader();
            superData = loader.getChildOfType(tc.getName(),superName);
        } catch( MetaDataNotFoundException ex ) {
            throw new MetaDataException( "Referenced superData ["+superName+"] with type ["+tc.getName()+"] "+
                    "was not found by superRef on model: "+model);
        }
        return superData;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy