org.openehealth.ipf.modules.cda.builder.CDAR2MetaObjectGraphBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.openehealth.ipf.modules.cda.builder.CDAR2MetaObjectGraphBuilder.java

Source

/**
 * Copyright 2009 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *     
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.openehealth.ipf.modules.cda.builder;

import groovy.lang.Closure;
import groovy.util.Factory;
import groovytools.builder.MetaBuilder;
import groovytools.builder.MetaObjectGraphBuilder;
import groovytools.builder.SchemaNode;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.Enumerator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.impl.EAttributeImpl;
import org.eclipse.emf.ecore.impl.EClassImpl;
import org.openhealthtools.ihe.common.cdar2.CDAR2Package;

import java.util.Map;

public class CDAR2MetaObjectGraphBuilder extends MetaObjectGraphBuilder {

    static final CDAR2Package ePackage = CDAR2Package.eINSTANCE;
    private static final Log LOG = LogFactory.getLog(CDAR2MetaObjectGraphBuilder.class);

    public CDAR2MetaObjectGraphBuilder(MetaBuilder metaBuilder, SchemaNode defaultSchema, Factory defaultFactory) {
        super(metaBuilder, defaultSchema, defaultFactory, null);
    }

    public CDAR2MetaObjectGraphBuilder(MetaBuilder metaBuilder, SchemaNode defaultSchema, Factory defaultFactory,
            Closure objectVisitor) {
        super(metaBuilder, defaultSchema, defaultFactory, objectVisitor);
    }

    @Override
    @SuppressWarnings("unchecked")
    protected Factory resolveFactory(Object name, Map attrs, Object value) {
        SchemaNode schema = getCurrentSchema();
        Object factoryAttr = findSchemaAttribute(schema, "factory");

        if (factoryAttr == null) {
            // resolve property factory for inherited property definitions
            if (schema.parent().name() == "properties") {
                SchemaNode mergedProperties = getMergedProperties((SchemaNode) schema.parent().parent());
                SchemaNode mergedNamedDefinition = (SchemaNode) mergedProperties.firstChild(name.toString());
                factoryAttr = findSchemaAttribute(mergedNamedDefinition, "factory");
            }
        }

        if (factoryAttr instanceof String) {
            // Replace String attribute by Factory instance

            Object factory = CDAR2Factory.factoryFor(factoryAttr.toString());
            schema.attributes().put("factory", factory);
        }
        // as of check attribute is not propagated to the extension deifinitions
        Object checkAttr = findSchemaAttribute(schema, "check");
        if (checkAttr != null)
            schema.attributes().put("check", checkAttr);
        return super.resolveFactory(name, attrs, value);
    }

    /**
     * For EObject instances evaluate the value using the model factory In cases
     * the MetaBuilder's property attribute is used, evaluate also the objects
     * attribute name
     * 
     * @see MetaObjectGraphBuilder#setVariable(Object, SchemaNode, String,
     *      Object)
     */
    @Override
    public void setVariable(Object node, SchemaNode schema, String name, Object value) {
        if (node instanceof EObject) {
            SchemaNode mergedProperties = getMergedProperties(schema);
            SchemaNode propertySchema = (SchemaNode) mergedProperties.firstChild(name);
            if (propertySchema != null) {
                Object propertyAttr = propertySchema.attribute("property");
                if (propertyAttr != null) {
                    String propertyName = resolvePropertyAttrName(name, propertySchema, propertyAttr);
                    value = evaluateAttrValue(node, propertyName, value);
                } else {
                    value = evaluateAttrValue(node, name, value);
                }
            }
            super.setVariable(node, schema, name, value);
        } else {
            super.setVariable(node, schema, name, value);
        }
    }

    /**
     * Reads the 'property' attribute from the meta builder definition Allows
     * using it for value instaciation.
     */
    private Object evaluateAttrValue(Object node, String name, Object val) {
        if (val instanceof String) {
            try {
                return createAttributeByNameFromString(node.getClass(), name, val.toString());
            } catch (Exception e) {
                LOG.warn("Can't evaluate the value from String for the property " + name + " : " + e.getMessage());
                return val;
            }
        } else {
            return val;
        }
    }

    /**
     * In the cases when the propery attribute name is overriden using the Meta
     * Builder's 'property' attribute the name is resolved and used to reflect
     * in the EMF classifier definition
     */
    private String resolvePropertyAttrName(String propertyName, SchemaNode propertySchema, Object propertyAttr) {
        if (propertyAttr != null) {
            if (propertyAttr instanceof String) {
                return (String) propertyAttr;
            } else {
                throw MetaBuilder.createPropertyException(propertyName,
                        "'property' attribute of schema does not specify a string or closure.");
            }
        } else {
            return (String) propertySchema.name();
        }
    }

    /**
     * Reflect the attribute type and instanciate it properly from factory This
     * needs a revision if no factory is found: for generic Boolean, Real etc.
     * values
     */
    @SuppressWarnings("unchecked")
    protected Object createAttributeByNameFromString(Class klass, String key, String value) {
        EClassImpl classifierImpl = (EClassImpl) ePackage.getEClassifier(klass.getInterfaces()[0].getSimpleName());
        if (classifierImpl != null) {
            EList eList = classifierImpl.getEAllAttributes();
            for (Object anEList : eList) {
                EAttributeImpl attrImpl = (EAttributeImpl) anEList;
                if (attrImpl.getName().equals(key)) {
                    Class valueClass = attrImpl.getEAttributeType().getInstanceClass();
                    if (Enumerator.class.isAssignableFrom(valueClass)) { // create
                        // enumeration
                        // instance
                        Object instance = ((CDAR2Factory) getMetaBuilder().getDefaultBuildNodeFactory())
                                .createFromString(attrImpl.basicGetEAttributeType(), value);
                        return instance;
                    } else if (boolean.class.isAssignableFrom(valueClass)
                            || Boolean.class.isAssignableFrom(valueClass)) {
                        return value;
                    } else if (Number.class.isAssignableFrom(valueClass)) { // call
                        // the
                        // string
                        // constructor
                        return value;
                    }
                }
            }
            return value;
        } else {
            return null;
        }
    }
}