/******************************************************************************* * Copyright 2005-2007, CHISEL Group, University of Victoria, Victoria, BC, Canada * and IBM Corporation. All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * The Chisel Group, University of Victoria *******************************************************************************/ package net.sourceforge.tagsea.parsed.core.internal.operations; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.TreeSet; import net.sourceforge.tagsea.core.IWaypoint; import net.sourceforge.tagsea.core.TagSEAOperation; import net.sourceforge.tagsea.parsed.ParsedWaypointPlugin; import net.sourceforge.tagsea.parsed.core.IParsedWaypointDefinition; import net.sourceforge.tagsea.parsed.core.ParsedWaypointUtils; import net.sourceforge.tagsea.parsed.core.internal.KindedParsedWaypointDescriptor; import net.sourceforge.tagsea.parsed.core.internal.ParsedWaypointRegistry; import net.sourceforge.tagsea.parsed.core.internal.WaypointParsingTools; import net.sourceforge.tagsea.parsed.core.internal.WaypointParsingTools.WaypointDescriptorMatch; import net.sourceforge.tagsea.parsed.core.internal.resources.DocumentRegistry; import net.sourceforge.tagsea.parsed.parser.IParsedWaypointDescriptor; import net.sourceforge.tagsea.parsed.parser.IWaypointParseProblemCollector; import net.sourceforge.tagsea.parsed.parser.IWaypointParser; import org.eclipse.core.filebuffers.FileBuffers; import org.eclipse.core.filebuffers.ITextFileBuffer; import org.eclipse.core.filebuffers.LocationKind; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.Region; /** * Parses a given file for waypoints. Does a clean parse. * ONLY MEANT TO BE RUN FROM WITHIN AN AbstractWaypointUpdateOperation * @author Del Myers * */ public class ParseFileOperation extends TagSEAOperation { private IFile file; public ParseFileOperation(IFile file) { this.file = file; } public IStatus run(IProgressMonitor monitor) throws InvocationTargetException{ ParsedWaypointRegistry wpRegistry = ((ParsedWaypointRegistry)ParsedWaypointPlugin.getDefault().getParsedWaypointRegistry()); wpRegistry.touch(file); if (!file.isAccessible()) { //remove the waypoints. IWaypoint[] wps = wpRegistry.findWaypoints(file, IResource.DEPTH_ZERO); for (IWaypoint wp : wps) { if (wp.exists()) { wp.delete(); } } return Status.OK_STATUS; } monitor.beginTask("Parsing file " + file.getFullPath(), 103); IParsedWaypointDefinition[] defs = ParsedWaypointPlugin.getDefault().getParsedWaypointRegistry().getMatchingDefinitions(file); monitor.worked(1); if (defs == null || defs.length == 0) { //don't waste time or memory. monitor.done(); return Status.OK_STATUS; } boolean disconnect = false; ITextFileBuffer buffer = FileBuffers.getTextFileBufferManager().getTextFileBuffer(file.getFullPath(), LocationKind.IFILE); if (buffer == null) { try { FileBuffers.getTextFileBufferManager().connect( file.getFullPath(), LocationKind.IFILE, new SubProgressMonitor( monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK ) ); } catch (CoreException e) { monitor.done(); throw new InvocationTargetException(e); } buffer = FileBuffers.getTextFileBufferManager().getTextFileBuffer(file.getFullPath(), LocationKind.IFILE); disconnect = true; } if (buffer != null) { IDocument document = buffer.getDocument(); ISchedulingRule rule = file.getWorkspace().getRuleFactory().modifyRule(file); ArrayList<KindedParsedWaypointDescriptor> allDescriptors = new ArrayList<KindedParsedWaypointDescriptor>(); IWaypointParseProblemCollector collector = DocumentRegistry.INSTANCE; try { Job.getJobManager().beginRule(rule, new SubProgressMonitor(monitor, 25)); if (document != null) { ((DocumentRegistry)collector).clearProblems(document); for (IParsedWaypointDefinition def : defs) { IWaypointParser parser = def.getParser(); IParsedWaypointDescriptor[] descriptors = parser.parse(document, new IRegion[]{new Region(0, document.getLength())}, collector); for (IParsedWaypointDescriptor desc : descriptors) { allDescriptors.add(new KindedParsedWaypointDescriptor(desc, def.getKind())); } } List<IWaypoint> waypoints = resolveWaypoints(allDescriptors, collector, document); if (!buffer.isDirty()) { //backup the waypoints. wpRegistry.backup(waypoints.toArray(new IWaypoint[waypoints.size()])); } } } finally { Job.getJobManager().endRule(rule); } } if (disconnect) { try { FileBuffers.getTextFileBufferManager().disconnect( file.getFullPath(), LocationKind.IFILE, new SubProgressMonitor( monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK ) ); } catch (CoreException e) { throw new InvocationTargetException(e); } } monitor.done(); return Status.OK_STATUS; } /** * @param allDescriptors * @param collector */ private List<IWaypoint> resolveWaypoints( ArrayList<KindedParsedWaypointDescriptor> allDescriptors, IWaypointParseProblemCollector problems, IDocument document) { //delete the unused waypoints. TreeSet<String> unregisteredSet = new TreeSet<String>(); for (IParsedWaypointDefinition def : ParsedWaypointPlugin.getDefault().getParsedWaypointRegistry().getContributedDefinitions()) { unregisteredSet.add(def.getKind()); } for (IParsedWaypointDefinition def : ParsedWaypointPlugin.getDefault().getParsedWaypointRegistry().getRegisteredDefinitions()) { unregisteredSet.remove(def.getKind()); } for (IWaypoint wp : ParsedWaypointPlugin.getDefault().getParsedWaypointRegistry().getWaypointsForFile(file)) { if (unregisteredSet.contains(ParsedWaypointUtils.getKind(wp))) { if (wp.exists()) { WaypointParsingTools.deleteWaypoint(wp); } } } WaypointParsingTools.RegionGraph<IParsedWaypointDescriptor> overlaps = WaypointParsingTools.calculateOverlap(allDescriptors); LinkedList<KindedParsedWaypointDescriptor> goodWaypoints = new LinkedList<KindedParsedWaypointDescriptor>(); LinkedList<KindedParsedWaypointDescriptor> overlappingDescriptors = new LinkedList<KindedParsedWaypointDescriptor>(); for (KindedParsedWaypointDescriptor desc : allDescriptors) { int overlapCount = overlaps.getOverlapCount(desc); if (overlapCount > 0) { overlappingDescriptors.add(desc); problems.accept(new WaypointOverlapProblem(desc.getCharStart(), desc.getCharEnd()-desc.getCharStart(), document)); } else { goodWaypoints.add(desc); } } //delete the overlapping waypoints deleteOverlaps(overlappingDescriptors); return generateWaypoints(goodWaypoints); } /** * @param overlappingDescriptors */ private void deleteOverlaps( LinkedList<KindedParsedWaypointDescriptor> overlappingDescriptors) { HashMap<String, List<IParsedWaypointDescriptor>> waypointKinds = new HashMap<String, List<IParsedWaypointDescriptor>>(); for (KindedParsedWaypointDescriptor desc : overlappingDescriptors) { List<IParsedWaypointDescriptor> kindDescriptors = waypointKinds.get(desc.getKind()); if (kindDescriptors == null) { kindDescriptors = new ArrayList<IParsedWaypointDescriptor>(); waypointKinds.put(desc.getKind(), kindDescriptors); } kindDescriptors.add(desc); } for (String kind : waypointKinds.keySet()) { List<IParsedWaypointDescriptor> descriptorsList = waypointKinds.get(kind); IParsedWaypointDescriptor[] descriptors = descriptorsList.toArray(new IParsedWaypointDescriptor[descriptorsList.size()]); List<WaypointDescriptorMatch> matchings = WaypointParsingTools.organizeWaypoints( file, ParsedWaypointPlugin. getDefault().getParsedWaypointRegistry().getWaypointsForFile( file, kind ), descriptors, kind ); //delete the waypoint for (WaypointDescriptorMatch match : matchings) { if (match.waypoint != null) { match.waypoint.delete(); } } } } /** * @param goodWaypoints */ private List<IWaypoint> generateWaypoints( LinkedList<KindedParsedWaypointDescriptor> goodWaypoints) { HashMap<String, List<IParsedWaypointDescriptor>> waypointKinds = new HashMap<String, List<IParsedWaypointDescriptor>>(); for (KindedParsedWaypointDescriptor desc : goodWaypoints) { List<IParsedWaypointDescriptor> kindDescriptors = waypointKinds.get(desc.getKind()); if (kindDescriptors == null) { kindDescriptors = new ArrayList<IParsedWaypointDescriptor>(); waypointKinds.put(desc.getKind(), kindDescriptors); } kindDescriptors.add(desc); } //Make sure that all of the kinds that did exist are in the set of kinds. for (IWaypoint wp : ParsedWaypointPlugin.getDefault().getParsedWaypointRegistry().getWaypointsForFile(file)) { if (wp.exists()) { String kind = ParsedWaypointUtils.getKind(wp); if (!waypointKinds.containsKey(kind)) { //add an empty list. waypointKinds.put(kind, new LinkedList<IParsedWaypointDescriptor>()); } } } List<IWaypoint> generatedList = new LinkedList<IWaypoint>(); for (String kind : waypointKinds.keySet()) { List<IParsedWaypointDescriptor> descriptorsList = waypointKinds.get(kind); IParsedWaypointDescriptor[] descriptors = descriptorsList.toArray(new IParsedWaypointDescriptor[descriptorsList.size()]); List<WaypointDescriptorMatch> matchings = WaypointParsingTools.organizeWaypoints( file, ParsedWaypointPlugin. getDefault().getParsedWaypointRegistry().getWaypointsForFile( file, kind ), descriptors, kind ); generatedList.addAll(WaypointParsingTools.generateWaypoints(matchings, file, kind)); } return generatedList; } /** * @return the file */ public IFile getFile() { return file; } }