/**
* Copyright (C) 2008-2010, Squale Project - http://www.squale.org
*
* This file is part of Squale.
*
* Squale is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or any later version.
*
* Squale 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Squale. If not, see <http://www.gnu.org/licenses/>.
*/
package org.squale.squalix.util.repository;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.squale.jraf.commons.exception.JrafDaoException;
import org.squale.jraf.spi.persistence.ISession;
import org.squale.squalecommon.daolayer.component.AbstractComponentDAOImpl;
import org.squale.squalecommon.daolayer.component.MethodDAOImpl;
import org.squale.squalecommon.enterpriselayer.businessobject.component.AbstractComplexComponentBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.AbstractComponentBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.ClassBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.JspBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.MethodBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.PackageBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.ProjectBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.UmlClassBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.UmlInterfaceBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.UmlModelBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.UmlPackageBO;
/**
* Charger de faire persister les composants.
*/
public class ComponentRepository
{
/**
* S�parateur des champs de cl�s. Ne doit pas �tre un s�parateur utilis� par McCabe pour qualifier enti�rement un
* nom.
*/
private static final String KEY_SEPARATOR = "<=>";
/**
* Session de persistance.
*/
private ISession mSession = null;
/**
* Contient la liste des classes du projet
*/
private Map mClasses;
/**
* Contient la liste des m�thodes du projet
*/
private Map mMethods;
/**
* Liste des packages/namespaces du projet
*/
private Map mPackages;
/**
* Liste des Mod�les UML
*/
private Map mUmlModels;
/**
* Liste des packages UML
*/
private Map mUmlPackages;
/**
* Liste des Interfaces UML
*/
private Map mUmlInterface;
/**
* Contient la liste des classes UML du mod�le
*/
private Map mUmlClasses;
/**
* Contient la liste des pages JSP
*/
private Map mJSPs;
/**
* Projet sur lequel est r�alis�e l'analyse.
*/
private ProjectBO mProject;
/**
* Constructeur
*
* @param pProject le projet sur lequel est r�alis�e l'analyse.
* @param pSession la session de persistance
*/
public ComponentRepository( ProjectBO pProject, ISession pSession )
{
mProject = pProject;
mSession = pSession;
mClasses = new HashMap();
mMethods = new HashMap();
mPackages = new HashMap();
mUmlInterface = new HashMap();
mUmlModels = new HashMap();
mUmlClasses = new HashMap();
mUmlPackages = new HashMap();
mJSPs = new HashMap();
Collection children = mProject.getChildren();
if ( null != children )
{
Iterator it = children.iterator();
while ( it.hasNext() )
{
addToCollection( (AbstractComponentBO) it.next(), null );
}
}
}
/**
* Cr�e la cl� du composant pour �tre utilis�e avec l'adaptateur et ajoute le composant et ses enfants dans les
* collections locales associ�es.
*
* @param pComponent le composant � ajouter.
* @param pParentName le nom du parent si disponible.
*/
private void addToCollection( AbstractComponentBO pComponent, String pParentName )
{
// Cr�ation de la cl�
String newParentName = pParentName;
if ( null == newParentName )
{
newParentName = pComponent.getName();
}
else
{
newParentName += KEY_SEPARATOR + pComponent.getName();
}
Map map = getMapForComponent( pComponent );
if ( pComponent instanceof AbstractComplexComponentBO )
{
map.put( newParentName, pComponent );
Collection children = ( (AbstractComplexComponentBO) pComponent ).getChildren();
if ( null != children )
{
// Si le composant est complexe, alors on va r�appeler la m�thode sur
// chacun de ses enfants, de mani�re r�cursive pour parcourir tout
// l'arbre des composants du projet
Iterator it = children.iterator();
while ( it.hasNext() )
{
addToCollection( (AbstractComponentBO) it.next(), newParentName );
}
}
}
else
{
// Sinon, il s'agit d'une m�thode, on l'ajoute simplement � sa map
map.put( newParentName, pComponent );
}
}
/**
* Fait persister un composant ou le r�cup�re si il existe d�j�.
*
* @param pComponent le composant � rechercher ou � faire persister.
* @return le composant persistant.
* @throws JrafDaoException si erreur
*/
public AbstractComponentBO persisteComponent( AbstractComponentBO pComponent )
throws JrafDaoException
{
// On cr�e la liste de ses parents + le composant lui-m�me
List parents = getParents( pComponent );
AbstractComponentBO persistentParent = mProject;
int parentsSize = parents.size();
for ( int i = parents.size() - 1; i >= 0; i-- )
{
persistentParent = persisteComponent( persistentParent, (AbstractComponentBO) parents.get( i ) );
}
return persistentParent;
}
/**
* Construit l'arbre complet du composant.
*
* @param pComponent le composant
* @return la liste contenant les parents de pComponent et lui-m�me.
*/
private List getParents( AbstractComponentBO pComponent )
{
List parents = new ArrayList();
parents.add( pComponent );
AbstractComplexComponentBO parent = pComponent.getParent();
boolean hasCorrectParents = ( parent != null );
for ( ; parent != null && hasCorrectParents; parent = parent.getParent() )
{
if ( parent instanceof ProjectBO )
{
hasCorrectParents = false;
}
else
{
parents.add( parent );
}
}
return parents;
}
/**
* Fait persister un composant (ou le r�cup�re si il existe d�j�) en lui associant son parent d�j� persistant.
*
* @param pPersistentParent le parent du composant d�j� persistant.
* @param pComponent le composant � faire persister ou � rechercher
* @return le composant persistant
* @throws JrafDaoException si erreur
*/
private AbstractComponentBO persisteComponent( AbstractComponentBO pPersistentParent, AbstractComponentBO pComponent )
throws JrafDaoException
{
// On r�cup�re la map du composant
Map map = getMapForComponent( pComponent );
// On cr�e la cl� repr�sentant l'objet dans la map
String key = buildKey( pComponent );
AbstractComponentBO mapComponent = (AbstractComponentBO) map.get( key );
if ( null == mapComponent )
{
// il n'existe pas, on le cr�e et on sauvegarde l'objet en base
AbstractComponentDAOImpl dao = AbstractComponentDAOImpl.getInstance();
pComponent.setParent( (AbstractComplexComponentBO) pPersistentParent );
pComponent.setProject( mProject );
dao.save( mSession, pComponent );
// On ajoute l' �l�ment persistant � la map correspondante
map.put( key, pComponent );
mapComponent = pComponent;
}
else if ( pComponent instanceof ClassBO )
{
// cas particulier d'un classe qui peut �tre persist�e sans son fichier
ClassBO classPersistent = (ClassBO) mapComponent;
ClassBO classArg = (ClassBO) pComponent;
if ( null == classPersistent.getFileName() && null != classArg.getFileName() )
{
// On update la classe
AbstractComponentDAOImpl dao = AbstractComponentDAOImpl.getInstance();
classPersistent.setFileName( classArg.getFileName() );
dao.save( mSession, classPersistent );
}
}
return mapComponent;
}
/**
* Retrouve la map en fonction du type du composant.
*
* @param pComponent le composant
* @return la map dans laquelle pComponent doit �tre
*/
private Map getMapForComponent( AbstractComponentBO pComponent )
{
Map result = null;
// Chaque type de composant � sa map associ�e,
// on r�cup�re donc le v�ritable type de l'objet
// pass� en param�tre et on retourne sa map associ�e
if ( pComponent instanceof MethodBO )
{
// mMethods contient des MethodBO
result = mMethods;
}
else if ( pComponent instanceof ClassBO )
{
// mClasses contient des ClassBO
result = mClasses;
}
else if ( pComponent instanceof PackageBO )
{
// mPackages contient des PackageBO
result = mPackages;
}
else if ( pComponent instanceof UmlInterfaceBO )
{
// mUmlInterface contient des UmlInterfaceBO
result = mUmlInterface;
}
else if ( pComponent instanceof UmlModelBO )
{
// mUmlModels contient des UmlModelBO
result = mUmlModels;
}
else if ( pComponent instanceof UmlClassBO )
{
// mUmlClass contient des UmlClasslBO
result = mUmlClasses;
}
else if ( pComponent instanceof UmlPackageBO )
{
// mUmlPackage contient des UmlPackagelBO
result = mUmlPackages;
}
else if ( pComponent instanceof JspBO )
{
// mJSPs contient des JspBO
result = mJSPs;
}
return result;
}
/**
* Construit la cl� du composant qui correspond � la concat�nation de ses parents s�par�e par KEY_SEPARATOR
*
* @param pComponent le composant
* @return la cl� repr�sentant le composant dans les maps
*/
public String buildKey( AbstractComponentBO pComponent )
{
String key = pComponent.getName();
AbstractComponentBO parent = pComponent.getParent();
boolean hasCorrectParents = ( parent != null );
while ( hasCorrectParents )
{
if ( parent instanceof ProjectBO )
{
hasCorrectParents = false;
}
else
{
key = parent.getName() + KEY_SEPARATOR + key;
parent = parent.getParent();
hasCorrectParents = ( parent != null );
}
}
return key;
}
/**
* @return la session
*/
public ISession getSession()
{
return mSession;
}
/**
* @param pMethodName le nom de la m�thode � r�cup�rer
* @param pFileName le nom du fichier dans lequel se trouve la m�thode
* @param pAuditId l'id de l'audit
* @return la bonne m�thodBO
* @throws JrafDaoException en cas d'�chec
*/
public Collection getSimilarMethods( String pMethodName, String pFileName, long pAuditId )
throws JrafDaoException
{
AbstractComponentDAOImpl compDao = AbstractComponentDAOImpl.getInstance();
Collection result = new ArrayList( 0 );
MethodDAOImpl dao = MethodDAOImpl.getInstance();
result = dao.findMethodeByName( mSession, pMethodName, pFileName, pAuditId );
return result;
}
/**
* This method search the component give in arguments in the list of all componentBO already existent
*
* @param component Component to search
* @return The componentBO associate if it is found or null if it is not found
*/
public AbstractComponentBO getComponent( AbstractComponentBO component )
{
Map map = getMapForComponent( component );
String key = buildKey( component );
AbstractComponentBO persistentComponent = (AbstractComponentBO) map.get( key );
return persistentComponent;
}
/**
* This method give access to the attribute mClasses
*
* @return the list of classBO already persist
*/
public Map getClasses()
{
return mClasses;
}
/**
* This method give access to the attribute mMethods
*
* @return the list of methodBo already persist
*/
public Map getMethods()
{
return mMethods;
}
/**
* Compare two component by there key. This method use the buildKey() method of the ComponentRepository class to
* build the key
*
* @param pComponent First component to compare
* @param pComponentToCompare Second component to compare
* @return true if there key are the same
*/
public boolean compare( AbstractComponentBO pComponent, AbstractComponentBO pComponentToCompare )
{
boolean bool = false;
if ( buildKey( pComponent ).compareTo( buildKey( pComponentToCompare ) ) == 0 )
{
bool = true;
}
return bool;
}
}