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

org.plasma.sdo.access.provider.common.TraversalMapAssembler Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
/**
 *         PlasmaSDO™ License
 * 
 * This is a community release of PlasmaSDO™, a dual-license 
 * Service Data Object (SDO) 2.1 implementation. 
 * This particular copy of the software is released under the 
 * version 2 of the GNU General Public License. PlasmaSDO™ was developed by 
 * TerraMeta Software, Inc.
 * 
 * Copyright (c) 2013, TerraMeta Software, Inc. All rights reserved.
 * 
 * General License information can be found below.
 * 
 * This distribution may include materials developed by third
 * parties. For license and attribution notices for these
 * materials, please refer to the documentation that accompanies
 * this distribution (see the "Licenses for Third-Party Components"
 * appendix) or view the online documentation at 
 * .
 *  
 */
package org.plasma.sdo.access.provider.common;

// java imports
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.plasma.config.DataAccessProviderName;
import org.plasma.query.QueryException;
import org.plasma.query.model.AbstractPathElement;
import org.plasma.query.model.AbstractProperty;
import org.plasma.query.model.Path;
import org.plasma.query.model.PathElement;
import org.plasma.query.model.Property;
import org.plasma.query.model.Select;
import org.plasma.query.model.WildcardPathElement;
import org.plasma.query.model.WildcardProperty;
import org.plasma.query.visitor.DefaultQueryVisitor;
import org.plasma.query.visitor.QueryVisitor;
import org.plasma.sdo.access.DataAccessException;

import commonj.sdo.Type;

public class TraversalMapAssembler
{
    private static Log log = LogFactory.getLog(TraversalMapAssembler.class);

    private Type rootType;    
    private TraversalMap map;

    @SuppressWarnings("unused")
	private TraversalMapAssembler() {}

    public TraversalMapAssembler(Select select, Type rootType,
    		DataAccessProviderName providerName)
    {
        this.rootType = rootType;
        map = new TraversalMap(providerName);
        if (select.getProperties().size() == 0)
        	throw new DataAccessException("Select clause has no properties");
        QueryVisitor visitor = new DefaultQueryVisitor() {
        	@Override
            public void start(Property property)                                                                            
            {     
            	assembleProperty(property);                                                                                                          
                super.start(property);                                                                  
            } 
        	@Override
            public void start(WildcardProperty wildcardProperty)                                                                            
            {     
            	assembleProperty(wildcardProperty);                                                                                                          
                super.start(wildcardProperty);                                                                  
            }                                                                                                                                                                                                                                                                                                                                                               
        };
        select.accept(visitor);
    }

    public TraversalMap getMap()
    {
        return map;
    }

    private void assembleProperty(AbstractProperty abstractProperty) {
        Path path = null;
        if (abstractProperty instanceof Property) {
            path = ((Property)abstractProperty).getPath();
        }
        else if (abstractProperty instanceof WildcardProperty) {
            path = ((WildcardProperty)abstractProperty).getPath();
        }
        else
            throw new IllegalArgumentException("unknown property class, "
                    + abstractProperty.getClass().getName());
        if (path == null) {
            String[] names = findPropertyNames(this.rootType, abstractProperty);
            if (names.length == 1) {
                map.add(TraversalMap.DELIM_PATH, names[0]); // add a path-oriented entry         
                map.add(this.rootType.getURI() + "#" + this.rootType.getName(), names[0]); // add an entity-oriented entry                
            }
            else {
                map.add(TraversalMap.DELIM_PATH, names); // add a path-oriented entry         
                map.add(this.rootType.getURI() + "#" + this.rootType.getName(), names); // add an entity-oriented entry                
            }
        }
        else {
            assemblePath(path, this.rootType, TraversalMap.DELIM_PATH, 
                    path.getPathNodes().get(0).getPathElement(), 0, 
                    abstractProperty);
        }
    }
    
    private void assemblePath(Path path, Type currType, String currTraversalPath,
            AbstractPathElement currPathElement, 
            int curPathElementIndex, AbstractProperty abstractProperty) {
        
        // FIXME: use enum here
        if (currPathElement instanceof PathElement) {
            PathElement pathElement = (PathElement)currPathElement;
            commonj.sdo.Property prop = currType.getProperty(pathElement.getValue());
            if (prop.getType().isDataType())
                if (abstractProperty instanceof Property)
                    throw new QueryException("traversal path for property '" + ((Property)abstractProperty).getName() 
                        + "' from root '" + this.rootType.getName() + "' contains a non-reference property '" 
                        + prop.getName() + "'");
                else
                    throw new QueryException("traversal path for wildcard property " 
                        + "' from root '" + this.rootType.getName() + "' contains a non-reference property '" 
                        + prop.getName() + "'");

            //map.add(currType.getName(), pdef.getName()); // add an entity-oriented entry for path element 
            String nextTraversalPath = currTraversalPath + prop.getName() + TraversalMap.DELIM_PATH;                                   
            Type nextType = prop.getType();
            if (path.getPathNodes().size() > curPathElementIndex + 1) {
                int nextPathElementIndex = curPathElementIndex + 1;
                AbstractPathElement nextPathElement = path.getPathNodes().get(nextPathElementIndex).getPathElement();
                assemblePath(path, nextType, nextTraversalPath, nextPathElement, nextPathElementIndex, abstractProperty);
            }
            else {
                String[] names = findPropertyNames(nextType, abstractProperty);
                if (names.length == 1) {
                    map.add(nextTraversalPath, names[0]); // add a path-oriented entry         
                    map.add(nextType.getURI() + "#" + nextType.getName(), names[0]); // add an entity-oriented entry                
                }
                else {
                    map.add(nextTraversalPath, names); // add a path-oriented entry         
                    map.add(nextType.getURI() + "#" + nextType.getName(), names); // add an entity-oriented entry                
                }
            }
        }
        else if (currPathElement instanceof WildcardPathElement) {
            List properties = currType.getDeclaredProperties(); 
            
            for (commonj.sdo.Property prop : properties) {
            	if (prop.getType().isDataType())
            		continue;
                Type nextType = prop.getType();
                String nextTraversalPath = currTraversalPath + prop.getName() + TraversalMap.DELIM_PATH;                                   
                if (path.getPathNodes().size() > curPathElementIndex + 1) {
                    int nextPathElementIndex = curPathElementIndex + 1;
                    AbstractPathElement nextPathElement = path.getPathNodes().get(nextPathElementIndex).getPathElement();
                    assemblePath(path, nextType, nextTraversalPath, nextPathElement, nextPathElementIndex, abstractProperty);
                }
                else {
                    String[] names = findPropertyNames(nextType, abstractProperty);
                    if (names.length == 1) {
                        map.add(nextTraversalPath, names[0]); // add a path-oriented entry         
                        map.add(nextType.getURI() + "#" + nextType.getName(), names[0]); // add an entity-oriented entry                
                    }
                    else {
                        map.add(nextTraversalPath, names); // add a path-oriented entry         
                        map.add(nextType.getURI() + "#" + nextType.getName(), names); // add an entity-oriented entry                
                    }
                }
            }
        }
        else
            throw new IllegalArgumentException("unknown path element class, "
                    + currPathElement.getClass().getName());
    }
    
    private String[] findPropertyNames(Type type, AbstractProperty abstractProperty)
    {
        String[] result = null;       
        
        if (abstractProperty instanceof Property) {
            result = new String[1];
            String name = ((Property)abstractProperty).getName();
            type.getProperty(name);// just validates name
            result[0] = name;
        }
        else if (abstractProperty instanceof WildcardProperty) {
            WildcardProperty wildcardProperty = (WildcardProperty)abstractProperty;
            List list = new ArrayList();
            List props = type.getProperties();
            switch (wildcardProperty.getType())
            {
                default:
                case ALL:
                    for (commonj.sdo.Property prop : props)
                    	if (!prop.isMany())
                            list.add(prop.getName());
                    break;
                case REFERENCE:
                    for (commonj.sdo.Property prop : props)
                    	if (!prop.isMany() && !prop.getType().isDataType())
                            list.add(prop.getName());
                    break;
                case DATA:
                    for (commonj.sdo.Property prop : props)
                    	if (!prop.isMany() && prop.getType().isDataType())
                            list.add(prop.getName());
                    break;
            }
            result = new String[list.size()];
            list.toArray(result);
            
        }
        else
            throw new IllegalArgumentException("unknown property class, "
                + abstractProperty.getClass().getName());
        
        return result;
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy