/** * �������Ȩ���������ӹɷ����޹�˾ ��Ȩ���� * ϵͳ���ƣ�JRES Studio */ package com.hundsun.ares.studio.reference.internal; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.command.CompoundCommand; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl; import org.eclipse.emf.transaction.RecordingCommand; import org.eclipse.emf.transaction.RunnableWithResult; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.transaction.util.TransactionUtil; import com.hundsun.ares.studio.core.ARESCore; import com.hundsun.ares.studio.core.ARESElementChangedEvent; import com.hundsun.ares.studio.core.ARESModelException; import com.hundsun.ares.studio.core.IARESElement; import com.hundsun.ares.studio.core.IARESElementChangeListener; import com.hundsun.ares.studio.core.IARESProject; import com.hundsun.ares.studio.core.IARESResource; import com.hundsun.ares.studio.core.IReferencedLibrary; import com.hundsun.ares.studio.model.reference.ProjectReferenceCollection; import com.hundsun.ares.studio.model.reference.ReferenceFactory; import com.hundsun.ares.studio.model.reference.ReferenceInfo; import com.hundsun.ares.studio.model.reference.ReferenceTable; import com.hundsun.ares.studio.reference.ReferenceForBuilderManager; import com.hundsun.ares.studio.reference.ViewerUtils; /** * @author gongyf * */ public class ReferenceTableViewer { private static class RemoveProjectInfo extends RecordingCommand { private ReferenceTable table; private IARESProject project; /** * @param domain * @param table * @param project */ public RemoveProjectInfo(TransactionalEditingDomain domain, ReferenceTable table, IARESProject project) { super(domain); this.table = table; this.project = project; } /* (non-Javadoc) * @see org.eclipse.emf.transaction.RecordingCommand#doExecute() */ @Override protected void doExecute() { table.getProjects().remove(project); ReferenceForBuilderManager.getInstance().getProjects().remove(project); } } private static class RemoveResourceInfo extends RecordingCommand { private ReferenceTable table; private IARESResource resource; /** * @param domain * @param table * @param resource */ public RemoveResourceInfo(TransactionalEditingDomain domain, ReferenceTable table, IARESResource resource) { super(domain); this.table = table; this.resource = resource; } /* (non-Javadoc) * @see org.eclipse.emf.transaction.RecordingCommand#doExecute() */ @Override protected void doExecute() { ProjectReferenceCollection pi = table.getProjects().get(resource.getARESProject()); EList<ReferenceInfo> referenceInfoList = pi.getReferences().get(resource.getType()); if(referenceInfoList!=null){ for (Iterator<ReferenceInfo> iterator = referenceInfoList.iterator(); iterator.hasNext();) { ReferenceInfo ref = iterator.next(); if (ObjectUtils.equals(ref.getResource(), resource)) { iterator.remove(); } } } String[] refTypes = ViewerUtils.getRefTypesCanSupport(resource.getType()); if(refTypes.length==1 && ViewerUtils.isOnlyResourceOnlyRefType(refTypes[0]) ){ EList<ReferenceInfo> newReferences = new BasicEList<ReferenceInfo>(); pi.updateOnlyResourceOnlyRefTypecache(refTypes[0], newReferences); } if(StringUtils.endsWithIgnoreCase(resource.getType(), "stdfield")){ ReferenceForBuilderManager.getInstance().clearReferences(resource); } } } private static class ChangeResourceInfo extends RecordingCommand { private ReferenceTable table; private IARESResource resource; private Map<Object, Object> context; /** * @param domain * @param table * @param resource * @param context */ public ChangeResourceInfo(TransactionalEditingDomain domain, ReferenceTable table, IARESResource resource, Map<Object, Object> context) { super(domain); this.table = table; this.resource = resource; this.context = context; } /* (non-Javadoc) * @see org.eclipse.emf.transaction.RecordingCommand#doExecute() */ @Override protected void doExecute() { ProjectReferenceCollection pi = table.getProjects().get(resource.getARESProject()); List<ReferenceInfo> oldList = ViewerUtils.getReferenceInfos(table, resource); List<ReferenceInfo> newList = ViewerUtils.getReferenceInfos(resource, context); // �ҳ���������Ŀ��ɾ������Ŀ HashSet<ReferenceInfo> tempSetAll = new HashSet<ReferenceInfo>(); for (int i=0; i<oldList.size(); i++) { tempSetAll.add(oldList.get(i)); } HashSet<ReferenceInfo> setDup = new HashSet<ReferenceInfo>(); ArrayList<ReferenceInfo> newClean = new ArrayList<ReferenceInfo>(); for (ReferenceInfo referenceInfo: newList) { if (tempSetAll.add(referenceInfo)) { newClean.add(referenceInfo); } else { setDup.add(referenceInfo); } } ArrayList<ReferenceInfo> oldListClean = new ArrayList<ReferenceInfo>(); for (ReferenceInfo referenceInfo: oldList ) { if (setDup.add(referenceInfo)) { oldListClean.add(referenceInfo); } } EList<ReferenceInfo> referenceInfoList = pi.getReferences().get(resource.getType()); if(referenceInfoList!=null){ referenceInfoList.removeAll(oldListClean); referenceInfoList.addAll(newClean); String[] refTypes =ViewerUtils.getRefTypesCanSupport(resource.getType()); if(refTypes.length==1 && ViewerUtils.isOnlyResourceOnlyRefType(refTypes[0]) ){ EList<ReferenceInfo> newReferences = new BasicEList<ReferenceInfo>(); newReferences.addAll(newList); pi.updateOnlyResourceOnlyRefTypecache(refTypes[0], newReferences); } } if(StringUtils.endsWithIgnoreCase(resource.getType(), "stdfield")){ List<ReferenceInfo> changeReferenceInfoList = new ArrayList<ReferenceInfo>(); changeReferenceInfoList.addAll(oldListClean); changeReferenceInfoList.addAll(newClean); ReferenceForBuilderManager.getInstance().addReferences(resource, changeReferenceInfoList);//�������ʱ���õĸ������� } } } private static class AddProjectInfo extends RecordingCommand { private ReferenceTable table; private IARESProject project; private Map<String,List<ReferenceInfo>> infoMap ; /** * @param domain * @param table * @param project * @param collecion */ public AddProjectInfo(TransactionalEditingDomain domain, ReferenceTable table, IARESProject project, Map<String,List<ReferenceInfo>> infoMap ) { super(domain); this.table = table; this.project = project; this.infoMap = infoMap; } /* (non-Javadoc) * @see org.eclipse.emf.transaction.RecordingCommand#doExecute() */ @Override protected void doExecute() { ProjectReferenceCollection value = table.getProjects().get(project); if (value == null) { value = ReferenceFactory.eINSTANCE.createProjectReferenceCollection(); table.getProjects().put(project, value); } Set<String> resTypes = infoMap.keySet(); for(String type :resTypes){ if (value.getReferences().get(type)!=null){ value.getReferences().get(type).clear(); value.getReferences().get(type).addAll(infoMap.get(type)); String[] refTypes =ViewerUtils.getRefTypesCanSupport(type); if(refTypes.length==1 && ViewerUtils.isOnlyResourceOnlyRefType(refTypes[0]) ){ EList<ReferenceInfo> newReferences = new BasicEList<ReferenceInfo>(); newReferences.addAll(infoMap.get(type)); value.updateOnlyResourceOnlyRefTypecache(refTypes[0], newReferences); } }else{ EList<ReferenceInfo> referenceInfoList = new BasicEList<ReferenceInfo>(); referenceInfoList.addAll(infoMap.get(type)); value.getReferences().put(type, referenceInfoList); String[] refTypes =ViewerUtils.getRefTypesCanSupport(type); if(refTypes.length==1 && ViewerUtils.isOnlyResourceOnlyRefType(refTypes[0]) ){ EList<ReferenceInfo> newReferences = new BasicEList<ReferenceInfo>(); newReferences.addAll(infoMap.get(type)); value.updateOnlyResourceOnlyRefTypecache(refTypes[0], newReferences); } } } } } /** * �༭�ڴ�ͳ��������Ϣ�ı༭�� */ private TransactionalEditingDomain editingDomain; private ReferenceTable table; /** * ���ڱ�����й�Ԥ����ķ�Χ */ private Set<Scope> processedScopes = new HashSet<Scope>(); private IResourceChangeListener listener = new IResourceChangeListener() { @Override public void resourceChanged(IResourceChangeEvent event) { IResourceDelta delta = event.getDelta(); if (delta != null) { ARESElementDeltaVisitor visitor = new ARESElementDeltaVisitor(); try { delta.accept(visitor); synchronized (processedScopes) { CompoundCommand command = new CompoundCommand(); for (IARESElement element : visitor.getRemovedElements()) { if (element instanceof IARESProject) { // ���̱�ɾ������Ҫɾ��������ص����� // ��ɾ����� for (Iterator<Scope> iterator = processedScopes.iterator(); iterator .hasNext();) { Scope scope = iterator.next(); if (ObjectUtils.equals(scope.getProject(), element)) { iterator.remove(); } } // ɾ������ command.append(new RemoveProjectInfo(editingDomain, table, (IARESProject)element)); } else if (element instanceof IARESResource) { // ������Ѿ�����ķ�Χ�������������� IARESResource aresResource = (IARESResource) element; if (processedScopes.contains(new Scope(aresResource.getARESProject(), aresResource.getType()))) { command.append(new RemoveResourceInfo(editingDomain, table, aresResource)); } } } for (IARESElement element : visitor.getAddedOrChangedElements()) { // ��Ӻ��޸Ĺ����Dz���Ҫ����� if (element instanceof IARESResource) { IARESResource aresResource = (IARESResource) element; if (processedScopes.contains(new Scope(aresResource.getARESProject(), aresResource.getType()))) { Map<Object, Object> context = createReferenceProviderContext(); command.append(new ChangeResourceInfo(editingDomain, table, aresResource, context)); } } } excute(command); } } catch (CoreException e) { } } } }; /** * ���ڼ������ñ仯 */ private IARESElementChangeListener listener2 = new IARESElementChangeListener() { @Override public void elementChanged(ARESElementChangedEvent event) { if (event.getType() == ARESElementChangedEvent.RES_PATH) { IARESProject changedProject = (IARESProject) event.getElement(); synchronized (processedScopes) { for (Iterator<Scope> iterator = processedScopes.iterator(); iterator.hasNext();) { Scope scope = iterator.next(); if (ObjectUtils.equals(scope.getProject(), changedProject)) { iterator.remove(); } } excute(new RemoveProjectInfo(editingDomain, table, changedProject)); } } }}; /** * */ public ReferenceTableViewer() { // ����ģ�� editingDomain = TransactionalEditingDomain.Factory.INSTANCE.createEditingDomain(); Resource xmlRes = new XMLResourceImpl(); xmlRes.getContents().add(table = ReferenceFactory.eINSTANCE.createReferenceTable()); editingDomain.getResourceSet().getResources().add(xmlRes); ResourcesPlugin.getWorkspace().addResourceChangeListener(listener); ARESCore.addElementListener(listener2); } public void dispose() { ARESCore.removeElementListener(listener2); ResourcesPlugin.getWorkspace().removeResourceChangeListener(listener); editingDomain.dispose(); editingDomain = null; } /** * @return the table */ public ReferenceTable getTable() { return table; } /** * ������ȡ��Դ������Ϣʱ�������� * @return */ private Map<Object, Object> createReferenceProviderContext() { return Collections.emptyMap(); } /** * ������Ҫ�Ĺ��̣����һ�������Ѿ�������򲻻��ٽ��д��� * @param project * @param refType * @param useRequiredProjects */ private void process(IARESProject project, String refType, boolean useRequiredProjects) { synchronized (processedScopes) { List<IARESProject> needProcessProjects = new ArrayList<IARESProject>(); if (useRequiredProjects) { needProcessProjects.addAll(Arrays.asList(ViewerUtils.getAllRequiredProject(project))); } else { needProcessProjects.add(project); } Map<Object, Object> context = createReferenceProviderContext(); CompoundCommand command = new CompoundCommand(); String[] resTypes = ViewerUtils.getResTypesCanSupport(refType); for (IARESProject p : needProcessProjects) { for (String resType : resTypes) { Scope key = new Scope(p, resType); if (!processedScopes.contains(key)) { Map<String,List<ReferenceInfo>> infoMap = new HashMap<String,List<ReferenceInfo>>(); // ��Ҫ�ռ����̱�������ð����� List<IARESResource> resourceList = new ArrayList<IARESResource>(); // ������Ҫע�����һ���������Ϳ����Ƕ�����Դ�ṩ�ģ����߶���������Դ��һ����Դ�ṩ�� // FIXME try { String[] types = new String[]{resType}; resourceList.addAll(Arrays.asList(p.getResources(types))); for (IReferencedLibrary lib : p.getReferencedLibs()) { resourceList.addAll(Arrays.asList(lib.getResources(types))); } } catch (ARESModelException e) { } for (IARESResource res : resourceList) { if(infoMap.get(res.getType())!=null){ infoMap.get(res.getType()).addAll(ViewerUtils.getReferenceInfos(res, context)); }else{ List<ReferenceInfo> resInfoList = new ArrayList<ReferenceInfo>(); resInfoList.addAll(ViewerUtils.getReferenceInfos(res, context)); infoMap.put(res.getType(), resInfoList); } } //��ֹ��ģ�����û����Դ�����,��Ӧ��Դ���͵Ļ���Ϊnull��� if(infoMap.get(resType)==null ){ List<ReferenceInfo> resInfoList = new ArrayList<ReferenceInfo>(); infoMap.put(resType, resInfoList); } command.append(new AddProjectInfo(editingDomain, table, p, infoMap)); // ���ñ�� processedScopes.add(key); } } } excute(command); } } public List<ReferenceInfo> getReferenceInfos(final IARESProject project,final String refType,final String refName,final String refNamespace, final boolean useRequiredProjects) { process(project, refType, useRequiredProjects); try { return TransactionUtil.runExclusive(editingDomain, new RunnableWithResult.Impl<List<ReferenceInfo>>(){ @Override public void run() { List<ReferenceInfo> result = new ArrayList<ReferenceInfo>(); if (useRequiredProjects) { for (IARESProject p : ViewerUtils.getAllRequiredProject(project)) { ProjectReferenceCollection pi = table.getProjects().get(p); if (pi != null) { result.addAll(pi.getReferenceInfos(refType, refName, refNamespace)); } } } else { ProjectReferenceCollection pi = table.getProjects().get(project); if (pi != null) { result.addAll(pi.getReferenceInfos(refType, refName, refNamespace)); } } setResult(result); }}); } catch (InterruptedException e) { return Collections.emptyList(); } } public List<ReferenceInfo> getReferenceInfos(final IARESProject project,final String refType,final String refName, final boolean useRequiredProjects) { process(project, refType, useRequiredProjects); try { return TransactionUtil.runExclusive(editingDomain, new RunnableWithResult.Impl<List<ReferenceInfo>>(){ @Override public void run() { List<ReferenceInfo> result = new ArrayList<ReferenceInfo>(); if (useRequiredProjects) { for (IARESProject p : ViewerUtils.getAllRequiredProject(project)) { ProjectReferenceCollection pi = table.getProjects().get(p); if (pi != null) { result.addAll(pi.getReferenceInfos(refType, refName)); } } } else { ProjectReferenceCollection pi = table.getProjects().get(project); if (pi != null) { result.addAll(pi.getReferenceInfos(refType, refName)); } } setResult(result); }}); } catch (InterruptedException e) { return Collections.emptyList(); } } public List<ReferenceInfo> getFirstReferenceInfos(final IARESProject project,final String refType,final String refName,final String refNamespace, final boolean useRequiredProjects) { process(project, refType, useRequiredProjects); try { return TransactionUtil.runExclusive(editingDomain, new RunnableWithResult.Impl<List<ReferenceInfo>>(){ @Override public void run() { List<ReferenceInfo> result = new ArrayList<ReferenceInfo>(); if (useRequiredProjects) { for (IARESProject p : ViewerUtils.getAllRequiredProject(project)) { ProjectReferenceCollection pi = table.getProjects().get(p); if (pi != null) { result.addAll(pi.getFirstReferenceInfos(refType, refName,refNamespace)); } } } else { ProjectReferenceCollection pi = table.getProjects().get(project); if (pi != null) { result.addAll(pi.getFirstReferenceInfos(refType, refName,refNamespace)); } } setResult(result); }}); } catch (InterruptedException e) { return Collections.emptyList(); } } public List<ReferenceInfo> getReferenceInfos(final IARESProject project,final String refType, final boolean useRequiredProjects) { process(project, refType, useRequiredProjects); try { return TransactionUtil.runExclusive(editingDomain, new RunnableWithResult.Impl<List<ReferenceInfo>>(){ @Override public void run() { List<ReferenceInfo> result = new ArrayList<ReferenceInfo>(); if (useRequiredProjects) { for (IARESProject p : ViewerUtils.getAllRequiredProject(project)) { ProjectReferenceCollection pi = table.getProjects().get(p); if (pi != null) { result.addAll(pi.getReferenceInfos(refType)); } } } else { ProjectReferenceCollection pi = table.getProjects().get(project); if (pi != null) { result.addAll(pi.getReferenceInfos(refType)); } } setResult(result); }}); } catch (InterruptedException e) { return Collections.emptyList(); } } /** * ��ȡ��Դ���ݣ��õ���Դ�ṩ�Ŀ�������Ϣ * @param resource * @return */ public List<ReferenceInfo> getReferenceInfos(IARESResource resource) { return ViewerUtils.getReferenceInfos(resource, createReferenceProviderContext()); } /** * ִ�������޸����� * @param command */ private void excute(Command command) { editingDomain.getCommandStack().execute(command); editingDomain.getCommandStack().flush(); } }