/**
* OpenSpotLight - Open Source IT Governance Platform
*
* Copyright (c) 2009, CARAVELATECH CONSULTORIA E TECNOLOGIA EM INFORMATICA LTDA
* or third-party contributors as indicated by the @author tags or express
* copyright attribution statements applied by the authors. All third-party
* contributions are distributed under license by CARAVELATECH CONSULTORIA E
* TECNOLOGIA EM INFORMATICA LTDA.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
***********************************************************************
* OpenSpotLight - Plataforma de Governança de TI de Código Aberto
*
* Direitos Autorais Reservados (c) 2009, CARAVELATECH CONSULTORIA E TECNOLOGIA
* EM INFORMATICA LTDA ou como contribuidores terceiros indicados pela etiqueta
* @author ou por expressa atribuição de direito autoral declarada e atribuída pelo autor.
* Todas as contribuições de terceiros estão distribuídas sob licença da
* CARAVELATECH CONSULTORIA E TECNOLOGIA EM INFORMATICA LTDA.
*
* Este programa é software livre; você pode redistribuí-lo e/ou modificá-lo sob os
* termos da Licença Pública Geral Menor do GNU conforme publicada pela Free Software
* Foundation.
*
* Este programa é distribuído na expectativa de que seja útil, porém, SEM NENHUMA
* GARANTIA; nem mesmo a garantia implícita de COMERCIABILIDADE OU ADEQUAÇÃO A UMA
* FINALIDADE ESPECÍFICA. Consulte a Licença Pública Geral Menor do GNU para mais detalhes.
*
* Você deve ter recebido uma cópia da Licença Pública Geral Menor do GNU junto com este
* programa; se não, escreva para:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
/**
*
*/
package org.openspotlight.bundle.language.java.resolver;
import org.openspotlight.bundle.common.metamodel.link.AbstractTypeBind;
import org.openspotlight.bundle.language.java.metamodel.link.*;
import org.openspotlight.bundle.language.java.metamodel.node.*;
import org.openspotlight.common.util.InvocationCacheFactory;
import org.openspotlight.graph.SLContext;
import org.openspotlight.graph.GraphReaderorg.openspotlight.graph.SLLink;
import org.openspotlight.graph.Node;
import org.openspotlight.graph.query.SLQueryApi;
import org.openspotlight.graph.query.SLQueryResult;
import java.util.*;
import static java.lang.Class.forName;
import static java.text.MessageFormat.format;
import static java.util.Collections.reverse;
import static org.openspotlight.bundle.language.java.JavaConstants.ABSTRACT_CONTEXT;
import static org.openspotlight.common.util.Exceptions.*;
/**
* The Class JavaTypeResolver is a {@link TypeResolver} used for Java Programming Language.
*
* @author Luiz Fernando Teston - feu.teston@caravelatech.com
*/
public class JavaTypeResolver extends AbstractTypeResolver<JavaType> {
/**
* The Class {@link ByNameTypeFinder} executes a simple by name query
*/
private class ByNameTypeFinder extends DolarReplacerQueryExecutor {
/**
* The Constructor.
*
* @param s the s
*/
public ByNameTypeFinder(
final String s ) {
super(s);
}
/**
* Execute with this string.
*
* @param s the s
* @return the SL query result
* @throws Exception the exception
* @{inheritDoc
*/
@Override
protected SLQueryResult executeWithThisString( final String s ) throws Exception {
final SLQueryApi query = getSession().createQueryApi();
query.select().type(JavaType.class.getName()).subTypes().selectEnd().where().type(JavaType.class.getName()).subTypes().each().property(
"qualifiedName").equalsTo().value(
s).typeEnd().whereEnd();
final SLQueryResult result = query.execute();
return result;
}
}
/**
* This class executes a query replacing the dolar character '$' by dot to fill the way that Java Programming Language works.
*/
private abstract class DolarReplacerQueryExecutor {
/** The actual string. */
private final String actualString;
/**
* Instantiates a new dolar replacer query executor.
*
* @param s the s
*/
public DolarReplacerQueryExecutor(
final String s ) {
actualString = s.replaceAll("[$]", ".");
}
/**
* Execute with this string.
*
* @param s the s
* @return the sL query result
* @throws Exception the exception
*/
protected abstract SLQueryResult executeWithThisString( String s ) throws Exception;
/**
* Gets the new string.
*
* @return the new string
*/
protected String getNewString() {
return actualString;
}
/**
* Gets the preffered type.
*
* @param result the result
* @return the preffered type
* @throws Exception the exception
*/
private Node getPrefferedType( final SLQueryResult result ) throws Exception {
final Map<String, List<Node>> resultMap = new HashMap<String, List<Node>>();
for (final SLContext ctx : getOrderedActiveContexts()) {
resultMap.put(ctx.getID(), new ArrayList<Node>());
}
for (final Node n : result.getNodes()) {
final List<Node> resultList = resultMap.get(n.getContext().getID());
if (resultList != null) {
resultList.add(n);
if (resultList.size() > 1) {
logAndThrow(new IllegalStateException(
format(
"Two nodes of the same type and name on the same context: node {0} (parent {2}) inside context {1}",
n.getName(), n.getContext().getID(), n.getParent().getName())));
}
}
}
for (final SLContext ctx : getOrderedActiveContexts()) {
final List<Node> resultList = resultMap.get(ctx.getID());
if (resultList.size() > 0) {
return resultList.get(0);
}
}
return null;
}
/**
* Gets the type by all possible names.
*
* @return the type by all possible names
* @throws Exception the exception
*/
public Node getTypeByAllPossibleNames() throws Exception {
final Node result = getPrefferedType(executeWithThisString(actualString));
return result;
}
}
/**
* The Class ComplexTypeFinderQueryExecutor .
*/
private class TypesFromTheSamePackageQueryExecutor extends DolarReplacerQueryExecutor {
/** The all types from same packages. */
private final Collection<Node> allTypesFromSamePackages;
/**
* Instantiates a new complex type finder query executor.
*
* @param typeToSolve the type to solve
* @param allTypesFromSamePackages the all types from same packages
*/
public TypesFromTheSamePackageQueryExecutor(
final String typeToSolve, final Collection<Node> allTypesFromSamePackages ) {
super(typeToSolve);
this.allTypesFromSamePackages = allTypesFromSamePackages;
}
/**
* Execute with this string.
*
* @param s the s
* @return the SL query result
* @throws Exception the exception
* @{inheritDoc
*/
@Override
public SLQueryResult executeWithThisString( final String s ) throws Exception {
final SLQueryApi justTheTargetTypeQuery = getSession().createQueryApi();
justTheTargetTypeQuery.select().type(JavaType.class.getName()).subTypes().selectEnd().where().type(
JavaType.class.getName()).subTypes().each().property(
"simpleName").equalsTo().value(
s).typeEnd().whereEnd();
final SLQueryResult result = justTheTargetTypeQuery.execute(allTypesFromSamePackages);
return result;
}
}
/** The Constant implementationInheritanceLinks. */
private static final Set<Class<? extends SLLink>> implementationInheritanceLinks = new LinkedHashSet<Class<? extends SLLink>>();
/** The Constant interfaceInheritanceLinks. */
private static final Set<Class<? extends SLLink>> interfaceInheritanceLinks = new LinkedHashSet<Class<? extends SLLink>>();
/** The Constant primitiveHierarchyLinks. */
private static final Set<Class<? extends SLLink>> primitiveHierarchyLinks = new LinkedHashSet<Class<? extends SLLink>>();
/** The all kinds of inheritance links. */
private final Set<Class<? extends SLLink>> allKindsOfInheritanceLinks = new LinkedHashSet<Class<? extends SLLink>>();
/** The all kinds of inheritance links reversed. */
private final Set<Class<? extends SLLink>> allKindsOfInheritanceLinksReversed = new LinkedHashSet<Class<? extends SLLink>>();
/** The Constant primitiveTypes. */
private static final Set<Class<?>> primitiveTypes = new LinkedHashSet<Class<?>>();
/** The Constant concreteTypes. */
private static final Set<Class<?>> concreteTypes = new LinkedHashSet<Class<?>>();
/*
* Here the link behavior is defined. This static block is so much important
* because it can define the ordering behavior on the queries. It defines
* also the link priority.
*/
static {
JavaTypeResolver.implementationInheritanceLinks.add(Extends.class);
JavaTypeResolver.implementationInheritanceLinks.add(ImplicitExtends.class);
JavaTypeResolver.implementationInheritanceLinks.add(AbstractTypeBind.class);
JavaTypeResolver.interfaceInheritanceLinks.add(AbstractTypeBind.class);
JavaTypeResolver.interfaceInheritanceLinks.add(Implements.class);
JavaTypeResolver.interfaceInheritanceLinks.add(InterfaceExtends.class);
JavaTypeResolver.primitiveTypes.add(JavaTypePrimitive.class);
JavaTypeResolver.primitiveHierarchyLinks.add(Extends.class);// FIXME
concreteTypes.add(JavaTypeClass.class);
concreteTypes.add(JavaTypeEnum.class);
}
/**
* Creates the new cached java type finder.
*
* @param abstractContext the abstract context
* @param orderedActiveContexts the ordered active contexts
* @param enableBoxing the enable boxing
* @param session the session
* @return the java type resolver
*/
@SuppressWarnings( {"cast", "boxing"} )
public static JavaTypeResolver createNewCached( final SLContext abstractContext,
final List<SLContext> orderedActiveContexts,
final boolean enableBoxing,
final GraphReadGraphReader final JavaTypeResolver cached = (JavaTypeResolver)InvocationCacheFactory.createIntoCached(JavaTypeResolver.class,
new Class<?>[] {
SLContext.class,
List.class, boolean.class,
GraphReader.class}GraphReader new Object[] {abstractContext,
orderedActiveContexts,
enableBoxing, session});
return cached;
}
/**
* Creates the new uncached and slow java type finder. Normaly its better to use the method
* {@link #createNewCached(SLContext, List, boolean, org.openspotlight.graph.GraphReader)}. This method GraphReadersed on tests.
*
* @param abstractContext the abstract context
* @param orderedActiveContexts the ordered active contexts
* @param enableBoxing the enable boxing
* @param session the session
* @return the java type resolver
*/
@Deprecated
public static TypeResolver<JavaType> createNewUncachedAndSlow( final SLContext abstractContext,
final List<SLContext> orderedActiveContexts,
final boolean enableBoxing,
final GraphReader session ) {
retuGraphReaderver(abstractContext, orderedActiveContexts, enableBoxing, session);
}
/**
* Instantiates a new java type resolver. Normaly should be better to use the static factory method
* {@link #createNewCached(SLContext, List, boolean, org.openspotlight.graph.GraphReader)}.
*
* @param abstractGraphReader context
* @param orderedActiveContexts the ordered active contexts
* @param enableBoxing the enable boxing
* @param session the session
*/
protected JavaTypeResolver(
final SLContext abstractContext, final List<SLContext> orderedActiveContexts,
final boolean enableBoxing, final GraphReader session ) {
super(implementationInGraphReaderrfaceInheritanceLinks, primitiveHierarchyLinks, abstractContext,
orderedActiveContexts, primitiveTypes, concreteTypes, enableBoxing, session);
allKindsOfInheritanceLinks.add(AbstractTypeBind.class);
allKindsOfInheritanceLinks.add(Extends.class);
allKindsOfInheritanceLinks.add(ImplicitExtends.class);
allKindsOfInheritanceLinks.add(InterfaceExtends.class);
allKindsOfInheritanceLinks.add(Implements.class);
allKindsOfInheritanceLinks.add(ImplicitPrimitiveCast.class);
if (enableBoxing) {
allKindsOfInheritanceLinks.add(AutoboxedBy.class);
allKindsOfInheritanceLinks.add(Autoboxes.class);
}
final List<Class<? extends SLLink>> reversed = new ArrayList<Class<? extends SLLink>>(allKindsOfInheritanceLinks);
reverse(reversed);
allKindsOfInheritanceLinksReversed.addAll(reversed);
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #bestMatch(org.openspotlight.graph.Node,
* org.openspotlight.graph.Node, org.openspotlight.graph.Node)
*/
@Override
public <T extends JavaType> BestTypeMatch bestMatch( final T reference,
final T t1,
final T t2 ) throws InternalJavaFinderError {
try {
if (reference.equals(t1)) {
if (t1.equals(t2)) {
return BestTypeMatch.SAME;
}
return BestTypeMatch.T1;
}
if (reference.equals(t2)) {
return BestTypeMatch.T2;
}
if (this.isPrimitiveType(reference)) {
final boolean t1Primitive = this.isPrimitiveType(t1);
final boolean t2Primitive = this.isPrimitiveType(t2);
if (t1Primitive && !t2Primitive) {
return BestTypeMatch.T1;
}
if (t2Primitive && !t1Primitive) {
return BestTypeMatch.T2;
}
final Collection<ImplicitPrimitiveCast> linksT1 = getSession().getLink(ImplicitPrimitiveCast.class, t1,
reference);
final Collection<ImplicitPrimitiveCast> linksT2 = getSession().getLink(ImplicitPrimitiveCast.class, t2,
reference);
if (linksT1.size() != linksT2.size()) {
if (linksT1.size() > linksT2.size()) {
return BestTypeMatch.T1;
}
return BestTypeMatch.T2;
}
if (linksT1.size() > 0) {
final ImplicitPrimitiveCast linkT1 = linksT1.iterator().next();
final ImplicitPrimitiveCast linkT2 = linksT2.iterator().next();
if (linkT1.getDistance() < linkT2.getDistance()) {
return BestTypeMatch.T1;
} else if (linkT1.getDistance() > linkT2.getDistance()) {
return BestTypeMatch.T2;
}
}
return BestTypeMatch.SAME;
}
final boolean referenceTypeOfT1 = this.isTypeOf(reference, t1);
final boolean referenceTypeOfT2 = this.isTypeOf(reference, t2);
if (!(referenceTypeOfT1 && referenceTypeOfT2)) {
if (referenceTypeOfT1) {
return BestTypeMatch.T1;
}
if (referenceTypeOfT2) {
return BestTypeMatch.T2;
}
return BestTypeMatch.SAME;
}
final int referenceParentsCount = this.countConcreteParents(reference,
IncludedResult.DO_NOT_INCLUDE_ACTUAL_TYPE_ON_RESULT);
final int t1ParentsCount = this.countConcreteParents(t1, IncludedResult.DO_NOT_INCLUDE_ACTUAL_TYPE_ON_RESULT);
final int t2ParentsCount = this.countConcreteParents(t2, IncludedResult.DO_NOT_INCLUDE_ACTUAL_TYPE_ON_RESULT);
final int x = referenceParentsCount - t1ParentsCount;
final int y = referenceParentsCount - t2ParentsCount;
if (y == x) {
return BestTypeMatch.SAME;
} else if (y > x) {
return BestTypeMatch.T1;
}
return BestTypeMatch.T2;
} catch (final Exception e) {
throw logAndReturnNew(e, InternalJavaFinderError.class);
}
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #countAllChildren(org.openspotlight.graph.Node,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.IncludedResult)
*/
@Override
public <T extends JavaType> int countAllChildren( final T activeType,
final IncludedResult includedResult ) throws InternalJavaFinderError {
return this.getAllChildren(activeType, ResultOrder.ASC, includedResult).size();
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #countAllParents(org.openspotlight.graph.Node,
* org.openspotlight.bundle.
* dap.language.java.resolver.TypeResolver.IncludedResult)
*/
@Override
public <T extends JavaType> int countAllParents( final T activeType,
final IncludedResult includedResult ) throws InternalJavaFinderError {
return this.getAllParents(activeType, ResultOrder.ASC, includedResult).size();
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #countConcreteChildren(org.openspotlight.graph.Node,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.IncludedResult)
*/
@Override
public <T extends JavaType> int countConcreteChildren( final T activeType,
final IncludedResult includedResult ) throws InternalJavaFinderError {
return this.getConcreteChildren(activeType, ResultOrder.ASC, includedResult).size();
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #countConcreteParents(org.openspotlight.graph.Node,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.IncludedResult)
*/
@Override
public <T extends JavaType> int countConcreteParents( final T activeType,
final IncludedResult includedResult ) throws InternalJavaFinderError {
return this.getConcreteParents(activeType, ResultOrder.ASC, includedResult).size();
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #countInterfaceChildren(org.openspotlight.graph.Node,
* org.openspotlight.
* bundle.dap.language.java.resolver.TypeResolver.IncludedResult)
*/
@Override
public <T extends JavaType> int countInterfaceChildren( final T activeType,
final IncludedResult includedResult ) throws InternalJavaFinderError {
return this.getInterfaceChildren(activeType, ResultOrder.ASC, includedResult).size();
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #countInterfaceParents(org.openspotlight.graph.Node,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.IncludedResult)
*/
@Override
public <T extends JavaType> int countInterfaceParents( final T activeType,
final IncludedResult includedResult ) throws InternalJavaFinderError {
return this.getInterfaceParents(activeType, ResultOrder.ASC, includedResult).size();
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #getAllChildren(org.openspotlight.graph.Node,
* org.openspotlight.bundle.dap
* .language.java.resolver.TypeResolver.ResultOrder,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.IncludedResult)
*/
@Override
public <T extends JavaType, A extends T> List<T> getAllChildren( final A activeType,
final ResultOrder order,
final IncludedResult includedResult )
throws InternalJavaFinderError {
return this.getAllChildrenByAllLinkTypes(activeType, order, JavaType.class, includedResult, Recursive.FULLY_RECURSIVE);
}
/**
* Gets the all children by all link types.
*
* @param activeType the active type
* @param order the order
* @param typeToFilter the type to filter
* @param includedResult the included result
* @param recursive the recursive
* @return the all children by all link types
* @throws InternalJavaFinderError the internal java finder error
*/
protected <T extends JavaType, A extends JavaType> List<T> getAllChildrenByAllLinkTypes( final A activeType,
final ResultOrder order,
final Class<? extends JavaType> typeToFilter,
final IncludedResult includedResult,
final Recursive recursive )
throws InternalJavaFinderError {
try {
final Set<Node> resultSet = new LinkedHashSet<Node>();
resultSet.add(activeType);
int lastSize = resultSet.size();
int actualSize = -1;
biggerLoop: while (lastSize != actualSize) {
lastSize = resultSet.size();
final Map<Class<? extends SLLink>, List<Node>> deltasFromEachType = new HashMap<Class<? extends SLLink>, List<Node>>();
for (final Class<? extends SLLink> linkType : allKindsOfInheritanceLinksReversed) {
deltasFromEachType.put(linkType, new ArrayList<Node>());
}
for (final Class<? extends SLLink> linkType : allKindsOfInheritanceLinksReversed) {
final SLQueryApi inheritanceTreeQuery = getSession().createQueryApi();
inheritanceTreeQuery.select().type(JavaType.class.getName()).subTypes().comma().byLink(linkType.getName()).a().selectEnd();
final Collection<Node> resultFromQuery = inheritanceTreeQuery.execute(new ArrayList<Node>(resultSet)).getNodes();
for (final Node possibleDelta : resultFromQuery) {
if (!resultSet.contains(possibleDelta)) {
deltasFromEachType.get(linkType).add(possibleDelta);
}
}
switch (recursive) {
case FULLY_RECURSIVE:
resultSet.addAll(resultFromQuery);
break;
case ONLY_DIRECT_PARENTS:
if (resultFromQuery.size() > 0) {
boolean changed = false;
for (final Node t : resultFromQuery) {
if (typeToFilter.isAssignableFrom(forName(t.getTypeName()))) {
changed = true;
resultSet.add(t);
}
}
if (changed) {
break biggerLoop;
}
}
break;
default:
throw logAndReturn(new IllegalStateException());
}
}
for (final Class<? extends SLLink> linkType : allKindsOfInheritanceLinksReversed) {
final List<Node> deltas = deltasFromEachType.get(linkType);
// fixing the node order
resultSet.removeAll(deltas);
resultSet.addAll(deltas);
}
actualSize = resultSet.size();
}
final List<T> typedInheritedTypes = new LinkedList<T>();
for (final Node n : resultSet) {
if (n.getContext().getID().equals(ABSTRACT_CONTEXT)) {
if (!JavaTypePrimitive.class.isAssignableFrom(forName(n.getTypeName()))) {
continue;
}
}
if (!getOrderedActiveContexts().contains(n.getContext())) {
continue;
}
if (typeToFilter.isAssignableFrom(forName(n.getTypeName())) || n.equals(activeType)) {
@SuppressWarnings( "unchecked" )
final T typed = (T)this.getTypedNode(n);
typedInheritedTypes.add(typed);
}
}
// typedInheritedTypes.remove(activeType);
switch (includedResult) {
case DO_NOT_INCLUDE_ACTUAL_TYPE_ON_RESULT:
typedInheritedTypes.remove(activeType);
break;
case INCLUDE_ACTUAL_TYPE_ON_RESULT:
break;
default:
throw logAndReturn(new IllegalStateException(
"Unexpected return on case statement depending on enum constants declared on org.openspotlight.bundle.dap.language.java.support.TypeFinder.IncludedResult."
+ includedResult.name()));
}
return this.order(order, typedInheritedTypes);
} catch (final Exception e) {
throw logAndReturnNew(e, InternalJavaFinderError.class);
}
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #getAllParents(org.openspotlight.graph.Node,
* org.openspotlight.bundle.dap
* .language.java.resolver.TypeResolver.ResultOrder,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.IncludedResult)
*/
@Override
public <T extends JavaType, A extends T> List<T> getAllParents( final A activeType,
final ResultOrder order,
final IncludedResult includedResult )
throws InternalJavaFinderError {
return this.getParentsByLinkTypes(activeType, order, allKindsOfInheritanceLinks, includedResult,
Recursive.FULLY_RECURSIVE);
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #getConcreteChildren(org.openspotlight.graph.Node,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.ResultOrder,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.IncludedResult)
*/
@Override
public <T extends JavaType, A extends T> List<T> getConcreteChildren( final A activeType,
final ResultOrder order,
final IncludedResult includedResult )
throws InternalJavaFinderError {
return this.getAllChildrenByAllLinkTypes(activeType, order, JavaTypeClass.class, includedResult,
Recursive.FULLY_RECURSIVE);
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #getConcreteParents(org.openspotlight.graph.Node,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.ResultOrder,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.IncludedResult)
*/
@Override
public <T extends JavaType, A extends JavaType> List<T> getConcreteParents( final A activeType,
final ResultOrder order,
final IncludedResult includedResult )
throws InternalJavaFinderError {
return this.getParentsByLinkTypes(activeType, order, implementationInheritanceLinks, includedResult,
Recursive.FULLY_RECURSIVE);
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #getDirectConcreteChildren(org.openspotlight.graph.Node)
*/
@Override
public <T extends JavaType, A extends T> List<T> getDirectConcreteChildren( final A activeType )
throws InternalJavaFinderError {
return this.getAllChildrenByAllLinkTypes(activeType, ResultOrder.DESC, JavaTypeClass.class,
IncludedResult.DO_NOT_INCLUDE_ACTUAL_TYPE_ON_RESULT,
Recursive.ONLY_DIRECT_PARENTS);
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #getDirectConcreteParents(org.openspotlight.graph.Node)
*/
@Override
public <T extends JavaType, A extends T> List<T> getDirectConcreteParents( final A activeType )
throws InternalJavaFinderError {
return this.getParentsByLinkTypes(activeType, ResultOrder.DESC, implementationInheritanceLinks,
IncludedResult.DO_NOT_INCLUDE_ACTUAL_TYPE_ON_RESULT, Recursive.ONLY_DIRECT_PARENTS);
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #getDirectInterfaceChildren(org.openspotlight.graph.Node)
*/
@Override
public <T extends JavaType, A extends T> List<T> getDirectInterfaceChildren( final A activeType )
throws InternalJavaFinderError {
return this.getAllChildrenByAllLinkTypes(activeType, ResultOrder.DESC, JavaTypeInterface.class,
IncludedResult.DO_NOT_INCLUDE_ACTUAL_TYPE_ON_RESULT,
Recursive.ONLY_DIRECT_PARENTS);
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #getDirectInterfaceParents(org.openspotlight.graph.Node)
*/
@Override
public <T extends JavaType, A extends T> List<T> getDirectInterfaceParents( final A activeType )
throws InternalJavaFinderError {
final List<T> superTypes = this.getConcreteParents(activeType, ResultOrder.ASC,
IncludedResult.INCLUDE_ACTUAL_TYPE_ON_RESULT);
final List<T> result = new ArrayList<T>();
for (final T n : superTypes) {
final List<T> currentResult = this.getParentsByLinkTypes(n, ResultOrder.DESC, interfaceInheritanceLinks,
IncludedResult.DO_NOT_INCLUDE_ACTUAL_TYPE_ON_RESULT,
Recursive.ONLY_DIRECT_PARENTS);
if (currentResult.size() > 0) {
result.add(currentResult.get(0));
break;
}
}
return result;
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #getInterfaceChildren(org.openspotlight.graph.Node,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.ResultOrder,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.IncludedResult)
*/
@Override
public <T extends JavaType, A extends T> List<T> getInterfaceChildren( final A activeType,
final ResultOrder order,
final IncludedResult includedResult )
throws InternalJavaFinderError {
return this.getAllChildrenByAllLinkTypes(activeType, order, JavaTypeInterface.class, includedResult,
Recursive.FULLY_RECURSIVE);
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #getInterfaceParents(org.openspotlight.graph.Node,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.ResultOrder,
* org.openspotlight.bundle
* .dap.language.java.resolver.TypeResolver.IncludedResult)
*/
@Override
public <T extends JavaType, A extends T> List<T> getInterfaceParents( final A activeType,
final ResultOrder order,
final IncludedResult includedResult )
throws InternalJavaFinderError {
final List<T> superTypes = this.getConcreteParents(activeType, ResultOrder.ASC, includedResult);
final Set<T> result = new LinkedHashSet<T>();
for (final T n : superTypes) {
final List<T> currentResult = this.getParentsByLinkTypes(n, ResultOrder.ASC, interfaceInheritanceLinks,
IncludedResult.DO_NOT_INCLUDE_ACTUAL_TYPE_ON_RESULT,
Recursive.FULLY_RECURSIVE);
result.addAll(currentResult);
}
switch (includedResult) {
case DO_NOT_INCLUDE_ACTUAL_TYPE_ON_RESULT:
result.remove(activeType);
break;
case INCLUDE_ACTUAL_TYPE_ON_RESULT:
result.add(activeType);
break;
default:
throw logAndReturn(new IllegalStateException(
"Unexpected return on case statement depending on enum constants declared on org.openspotlight.bundle.dap.language.java.support.TypeFinder.IncludedResult."
+ includedResult.name()));
}
ResultOrder newOrder;
switch (order) {
case ASC:
newOrder = ResultOrder.DESC;
break;
case DESC:
newOrder = ResultOrder.ASC;
break;
default:
throw new IllegalStateException();
}
return this.order(newOrder, new ArrayList<T>(result));
}
/**
* Gets the parents by link types.
*
* @param activeType the active type
* @param order the order
* @param linkType the link type
* @param includedResult the included result
* @param recursive the recursive
* @return the parents by link types
* @throws InternalJavaFinderError the internal java finder error
*/
protected <T extends JavaType, A extends JavaType> List<T> getParentsByLinkTypes( final A activeType,
final ResultOrder order,
final Class<? extends SLLink> linkType,
final IncludedResult includedResult,
final Recursive recursive )
throws InternalJavaFinderError {
final HashSet<Class<? extends SLLink>> links = new HashSet<Class<? extends SLLink>>();
links.add(linkType);
return this.getParentsByLinkTypes(activeType, order, links, includedResult, recursive);
}
/**
* Gets the parents by link types.
*
* @param activeType the active type
* @param order the order
* @param linkTypes the link types
* @param includedResult the included result
* @param recursive the recursive
* @return the parents by link types
* @throws InternalJavaFinderError the internal java finder error
*/
protected <T extends JavaType, A extends JavaType> List<T> getParentsByLinkTypes( final A activeType,
final ResultOrder order,
final Set<Class<? extends SLLink>> linkTypes,
final IncludedResult includedResult,
final Recursive recursive )
throws InternalJavaFinderError {
try {
final Set<Node> resultSet = new LinkedHashSet<Node>();
resultSet.add(activeType);
int lastSize = resultSet.size();
int actualSize = -1;
biggerLoop: while (lastSize != actualSize) {
lastSize = resultSet.size();
final Map<Class<? extends SLLink>, List<Node>> deltasFromEachType = new HashMap<Class<? extends SLLink>, List<Node>>();
for (final Class<? extends SLLink> linkType : linkTypes) {
deltasFromEachType.put(linkType, new ArrayList<Node>());
}
for (final Class<? extends SLLink> linkType : linkTypes) {
final SLQueryApi inheritanceTreeQuery = getSession().createQueryApi();
inheritanceTreeQuery.select().type(JavaType.class.getName()).subTypes().comma().byLink(linkType.getName()).b().selectEnd();
final Collection<Node> resultFromQuery = inheritanceTreeQuery.execute(new ArrayList<Node>(resultSet)).getNodes();
for (final Node possibleDelta : resultFromQuery) {
if (!resultSet.contains(possibleDelta)) {
deltasFromEachType.get(linkType).add(possibleDelta);
}
}
switch (recursive) {
case FULLY_RECURSIVE:
resultSet.addAll(resultFromQuery);
break;
case ONLY_DIRECT_PARENTS:
if (resultFromQuery.size() > 0) {
resultSet.addAll(resultFromQuery);
break biggerLoop;
}
break;
default:
throw logAndReturn(new IllegalStateException());
}
}
for (final Class<? extends SLLink> linkType : linkTypes) {
final List<Node> deltas = deltasFromEachType.get(linkType);
// fixing the node order
resultSet.removeAll(deltas);
resultSet.addAll(deltas);
}
actualSize = resultSet.size();
}
final ArrayList<T> typedInheritedTypes = new ArrayList<T>(resultSet.size());
for (final Node n : resultSet) {
if (n.getContext().getID().equals(ABSTRACT_CONTEXT) || !getOrderedActiveContexts().contains(n.getContext())) {
continue;
}
@SuppressWarnings( "unchecked" )
final T typed = (T)this.getTypedNode(n);
typedInheritedTypes.add(typed);
}
switch (includedResult) {
case DO_NOT_INCLUDE_ACTUAL_TYPE_ON_RESULT:
typedInheritedTypes.remove(activeType);
break;
case INCLUDE_ACTUAL_TYPE_ON_RESULT:
break;
default:
throw logAndReturn(new IllegalStateException(
"Unexpected return on case statement depending on enum constants declared on org.openspotlight.bundle.dap.language.java.support.TypeFinder.IncludedResult."
+ includedResult.name()));
}
return this.order(order, typedInheritedTypes);
} catch (final Exception e) {
throw logAndReturnNew(e, InternalJavaFinderError.class);
}
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #getPrimitiveFor(org.openspotlight.graph.Node)
*/
@Override
public <T extends JavaType, A extends JavaType> T getPrimitiveFor( final A wrappedType ) throws InternalJavaFinderError {
return this.<T, A>getUniqueResult(wrappedType, Autoboxes.class);
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #getType(java.lang.String)
*/
@SuppressWarnings( "unchecked" )
@Override
public <T extends JavaType> T getType( final String typeToSolve ) throws InternalJavaFinderError {
try {
final Node Node = new ByNameTypeFinder(typeToSolve).getTypeByAllPossibleNames();
if (Node == null) {
throw logAndReturn(new InternalJavaFinderError());
}
return (T)this.getTypedNode(Node);
} catch (final Exception e) {
throw logAndReturnNew(e, InternalJavaFinderError.class);
}
}
/**
* Gets the type.
*
* @param typeToSolve the type to solve
* @param activeType the active type
* @param parametrizedTypes the parametrized types
* @return the type
* @throws InternalJavaFinderError the internal java finder error
* @{inheritDoc
*/
@SuppressWarnings( "unchecked" )
@Override
public <T extends JavaType, A extends T> T getType( final String typeToSolve,
final A activeType,
final List<? extends JavaType> parametrizedTypes )
throws InternalJavaFinderError {
try {
final List<Node> inheritedTypes = new LinkedList<Node>();
inheritedTypes.add(activeType);
for (final Class<? extends SLLink> linkType : JavaTypeResolver.implementationInheritanceLinks) {
final SLQueryApi inheritanceTreeQuery = getSession().createQueryApi();
inheritanceTreeQuery.select().type(JavaType.class.getName()).subTypes().comma().byLink(linkType.getName()).b().selectEnd().keepResult().executeXTimes();
final Collection<Node> resultFromQuery = inheritanceTreeQuery.execute(inheritedTypes).getNodes();
inheritedTypes.addAll(resultFromQuery);
}
for (final Class<? extends SLLink> linkType : JavaTypeResolver.interfaceInheritanceLinks) {
final SLQueryApi inheritanceTreeQuery = getSession().createQueryApi();
inheritanceTreeQuery.select().type(JavaType.class.getName()).subTypes().comma().byLink(linkType.getName()).b().selectEnd().keepResult().executeXTimes();
final Collection<Node> resultFromQuery = inheritanceTreeQuery.execute(inheritedTypes).getNodes();
inheritedTypes.addAll(resultFromQuery);
}
final SLQueryApi allTypesFromSamePackagesQuery = getSession().createQueryApi();
allTypesFromSamePackagesQuery.select().type(JavaPackage.class.getName()).comma().byLink(PackageType.class.getName()).a().selectEnd();
allTypesFromSamePackagesQuery.select().type(JavaType.class.getName()).subTypes().comma().byLink(
PackageType.class.getName()).b().selectEnd();
final Collection<Node> allTypesFromSamePackages = allTypesFromSamePackagesQuery.execute(inheritedTypes).getNodes();
final Node Node = new TypesFromTheSamePackageQueryExecutor(typeToSolve, allTypesFromSamePackages).getTypeByAllPossibleNames();
if (Node == null) {
throw logAndReturn(new InternalJavaFinderError());
}
final T typed = (T)this.getTypedNode(Node);
return typed;
} catch (final Exception e) {
throw logAndReturnNew(e, InternalJavaFinderError.class);
}
}
/**
* Gets the typed node.
*
* @param Node the sl node
* @return the typed node
* @throws Exception the exception
* @{inheritDoc
*/
private <T extends JavaType> T getTypedNode( final Node Node ) throws Exception {
@SuppressWarnings( "unchecked" )
final T typedNode = (T)getSession().getNodeByID(Node.getID());
return typedNode;
}
/**
* Gets the unique result.
*
* @param type the type
* @param linkType the link type
* @return the unique result
* @throws InternalJavaFinderError the internal java finder error
*/
@SuppressWarnings( "unchecked" )
private <T extends JavaType, A extends JavaType> T getUniqueResult( final A type,
final Class<? extends SLLink> linkType )
throws InternalJavaFinderError {
try {
final ArrayList<Node> initial = new ArrayList<Node>();
initial.add(type);
final SLQueryApi inheritanceTreeQuery = getSession().createQueryApi();
inheritanceTreeQuery.select().type(JavaType.class.getName()).subTypes().comma().byLink(linkType.getName()).b().selectEnd();
final Collection<Node> resultFromQuery = inheritanceTreeQuery.execute(initial).getNodes();
if (resultFromQuery.size() > 0) {
return (T)this.getTypedNode(resultFromQuery.iterator().next());
}
throw new InternalJavaFinderError();
} catch (final Exception e) {
throw logAndReturnNew(e, InternalJavaFinderError.class);
}
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #getWrapperFor(org.openspotlight.graph.Node)
*/
@Override
public <T extends JavaType, A extends JavaType> T getWrapperFor( final A primitiveType ) throws InternalJavaFinderError {
return this.<T, A>getUniqueResult(primitiveType, AutoboxedBy.class);
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #isConcreteType(org.openspotlight.graph.Node)
*/
@Override
public <T extends JavaType> boolean isConcreteType( final T type ) throws InternalJavaFinderError {
try {
final String typeName = type.getTypeName();
return JavaTypeClass.class.isAssignableFrom(forName(typeName));
} catch (final Exception e) {
throw logAndReturnNew(e, InternalJavaFinderError.class);
}
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #isPrimitiveType(org.openspotlight.graph.Node)
*/
@Override
public <T extends JavaType> boolean isPrimitiveType( final T type ) throws InternalJavaFinderError {
try {
return JavaTypePrimitive.class.isAssignableFrom(forName(type.getTypeName()));
} catch (final Exception e) {
throw logAndReturnNew(e, InternalJavaFinderError.class);
}
}
/*
* (non-Javadoc)
*
* @see
* org.openspotlight.bundle.dap.language.java.resolver.AbstractTypeResolver
* #isTypeOf(org.openspotlight.graph.Node, org.openspotlight.graph.Node)
*/
@Override
public <T extends JavaType, A extends JavaType> boolean isTypeOf( final T implementation,
final A superType ) throws InternalJavaFinderError {
try {
final List<JavaType> children = this.<JavaType, A>getAllChildren(superType, ResultOrder.ASC,
IncludedResult.INCLUDE_ACTUAL_TYPE_ON_RESULT);
final boolean result = children.contains(implementation);
if (result) {
if (this.isPrimitiveType(implementation)) {
if (this.isConcreteType(superType)) {
final Collection<Autoboxes> links = getSession().getLink(Autoboxes.class, superType, implementation);
if (links.size() == 0) {
return false;
}
}
}
}
return result;
} catch (final Exception e) {
throw logAndReturnNew(e, InternalJavaFinderError.class);
}
}
/**
* Order the result
*
* @param order the order
* @param typedInheritedTypes the typed inherited types
* @return the list< t>
*/
private <T extends JavaType> List<T> order( final ResultOrder order,
final List<T> typedInheritedTypes ) {
switch (order) {
case ASC:
Collections.reverse(typedInheritedTypes);
return typedInheritedTypes;
case DESC:
return typedInheritedTypes;
default:
throw logAndReturn(new IllegalStateException(
"Unexpected return on case statement depending on enum constants declared on org.openspotlight.bundle.dap.language.java.support.TypeFinder.ResultOrder."
+ order.name()));
}
}
}