david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 1 | /******************************************************************************* |
amywu | ecebb04 | 2007-04-10 20:07:35 +0000 | [diff] [blame] | 2 | * Copyright (c) 2001, 2006 IBM Corporation and others. |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 3 | * All rights reserved. This program and the accompanying materials |
| 4 | * are made available under the terms of the Eclipse Public License v1.0 |
| 5 | * which accompanies this distribution, and is available at |
| 6 | * http://www.eclipse.org/legal/epl-v10.html |
amywu | ecebb04 | 2007-04-10 20:07:35 +0000 | [diff] [blame] | 7 | * |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 8 | * Contributors: |
| 9 | * IBM Corporation - initial API and implementation |
| 10 | * Jens Lukowski/Innoopract - initial renaming/restructuring |
| 11 | * |
| 12 | *******************************************************************************/ |
| 13 | package org.eclipse.wst.sse.ui.internal.reconcile; |
| 14 | |
| 15 | import java.util.ArrayList; |
| 16 | import java.util.Arrays; |
| 17 | import java.util.HashSet; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 18 | import java.util.List; |
| 19 | |
pavery | 46c93e7 | 2005-02-08 16:07:33 +0000 | [diff] [blame] | 20 | import org.eclipse.core.runtime.Platform; |
pavery | f4a08b3 | 2005-02-02 21:39:25 +0000 | [diff] [blame] | 21 | import org.eclipse.jface.text.BadLocationException; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 22 | import org.eclipse.jface.text.IDocument; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 23 | import org.eclipse.jface.text.IRegion; |
| 24 | import org.eclipse.jface.text.ITypedRegion; |
pavery | f4a08b3 | 2005-02-02 21:39:25 +0000 | [diff] [blame] | 25 | import org.eclipse.jface.text.TextUtilities; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 26 | import org.eclipse.jface.text.reconciler.AbstractReconcileStep; |
| 27 | import org.eclipse.jface.text.reconciler.DirtyRegion; |
| 28 | import org.eclipse.jface.text.reconciler.IReconcilableModel; |
| 29 | import org.eclipse.jface.text.reconciler.IReconcileResult; |
david_williams | 4ad020f | 2005-04-18 08:00:30 +0000 | [diff] [blame] | 30 | import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; |
| 31 | import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; |
david_williams | 4ad020f | 2005-04-18 08:00:30 +0000 | [diff] [blame] | 32 | import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredPartitioning; |
pavery | b0f98c5 | 2006-02-13 20:19:39 +0000 | [diff] [blame] | 33 | import org.eclipse.wst.sse.core.text.IStructuredPartitions; |
pavery | 0f11a86 | 2005-03-29 21:14:36 +0000 | [diff] [blame] | 34 | import org.eclipse.wst.sse.ui.internal.IReleasable; |
pavery | f4a08b3 | 2005-02-02 21:39:25 +0000 | [diff] [blame] | 35 | import org.eclipse.wst.sse.ui.internal.Logger; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 36 | |
| 37 | |
| 38 | /** |
| 39 | * ReconcileStep that knows about the annotation that it adds to the |
| 40 | * AnnotationModel. It knows how to create an annotation key (for smart |
| 41 | * removal later) It knows the partition types on which it can operate. It |
| 42 | * knows the scope on which it operates (for short circuiting) It knows if the |
| 43 | * Reconciler is reconciling the entire document. |
| 44 | * |
| 45 | * Clients must subclass this class. |
| 46 | * |
| 47 | * @author pavery |
| 48 | */ |
pavery | f4a08b3 | 2005-02-02 21:39:25 +0000 | [diff] [blame] | 49 | public abstract class StructuredReconcileStep extends AbstractReconcileStep implements IReleasable { |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 50 | |
david_williams | d6ee069 | 2005-02-23 16:38:05 +0000 | [diff] [blame] | 51 | /** debug flag */ |
| 52 | protected static final boolean DEBUG; |
| 53 | static { |
| 54 | String value = Platform.getDebugOption("org.eclipse.wst.sse.ui/debug/reconcilerjob"); //$NON-NLS-1$ |
| 55 | DEBUG = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$ |
| 56 | } |
| 57 | |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 58 | protected final IReconcileResult[] EMPTY_RECONCILE_RESULT_SET = new IReconcileResult[0]; |
pavery | 3b75d5d | 2005-11-10 02:27:12 +0000 | [diff] [blame] | 59 | |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 60 | /** |
| 61 | * It's possible for a partial step to get called on the same area twice |
| 62 | * (as w/ a full document reconcile) this list keeps track of area already |
| 63 | * covered. Should be reset() after the "batch" of reconciling is |
| 64 | * finished. |
| 65 | */ |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 66 | private HashSet fPartitionTypes = null; |
| 67 | |
| 68 | public StructuredReconcileStep() { |
| 69 | super(); |
| 70 | fPartitionTypes = new HashSet(); |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 71 | } |
| 72 | |
pavery | 55ae447 | 2005-02-16 23:00:16 +0000 | [diff] [blame] | 73 | public ReconcileAnnotationKey createKey(IStructuredDocumentRegion sdRegion, int scope) { |
david_williams | d6ee069 | 2005-02-23 16:38:05 +0000 | [diff] [blame] | 74 | |
| 75 | ITypedRegion tr = getPartition(sdRegion); |
pavery | b0f98c5 | 2006-02-13 20:19:39 +0000 | [diff] [blame] | 76 | String partitionType = (tr != null) ? tr.getType() : IStructuredPartitions.UNKNOWN_PARTITION; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 77 | return createKey(partitionType, scope); |
| 78 | } |
| 79 | |
david_williams | d6ee069 | 2005-02-23 16:38:05 +0000 | [diff] [blame] | 80 | /** |
| 81 | * @param sdRegion |
| 82 | * @return |
| 83 | */ |
pavery | b0763c0 | 2005-10-17 15:55:28 +0000 | [diff] [blame] | 84 | protected ITypedRegion getPartition(IStructuredDocumentRegion sdRegion) { |
david_williams | d6ee069 | 2005-02-23 16:38:05 +0000 | [diff] [blame] | 85 | ITypedRegion tr = null; |
| 86 | if (!sdRegion.isDeleted()) |
| 87 | tr = getPartition(sdRegion.getParentDocument(), sdRegion.getStartOffset()); |
| 88 | return tr; |
| 89 | } |
| 90 | |
| 91 | private ITypedRegion getPartition(IDocument doc, int offset) { |
| 92 | ITypedRegion tr = null; |
| 93 | // not sure why document would ever be null, but put in this |
| 94 | // guard for |
| 95 | // https://bugs.eclipse.org/bugs/show_bug.cgi?id=86069 |
| 96 | if (doc != null) { |
| 97 | try { |
pavery | 40dd89e | 2005-04-01 21:09:29 +0000 | [diff] [blame] | 98 | tr = TextUtilities.getPartition(doc, IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING, offset, false); |
david_williams | d6ee069 | 2005-02-23 16:38:05 +0000 | [diff] [blame] | 99 | } catch (BadLocationException e) { |
| 100 | if (DEBUG) |
david_williams | b9da93e | 2005-04-13 02:38:05 +0000 | [diff] [blame] | 101 | Logger.logException("problem getting partition at: " + offset, e); //$NON-NLS-1$ |
david_williams | d6ee069 | 2005-02-23 16:38:05 +0000 | [diff] [blame] | 102 | } |
| 103 | } |
| 104 | return tr; |
| 105 | } |
| 106 | |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 107 | /** |
| 108 | * Clients should use this method to create annotation keys as it |
| 109 | * registers the key for removal later. |
| 110 | * |
| 111 | * @param partitionType |
| 112 | * @param scope |
| 113 | * @return |
| 114 | */ |
pavery | 55ae447 | 2005-02-16 23:00:16 +0000 | [diff] [blame] | 115 | public ReconcileAnnotationKey createKey(String partitionType, int scope) { |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 116 | fPartitionTypes.add(partitionType); |
| 117 | return new ReconcileAnnotationKey(this, partitionType, scope); |
| 118 | } |
| 119 | |
| 120 | protected IDocument getDocument() { |
| 121 | IDocument doc = null; |
| 122 | IReconcilableModel rModel = getModel(); |
| 123 | if (rModel instanceof DocumentAdapter) { |
| 124 | doc = ((DocumentAdapter) rModel).getDocument(); |
| 125 | } |
| 126 | return doc; |
| 127 | } |
| 128 | |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 129 | public IReconcilableModel getModel() { |
| 130 | return getInputModel(); |
| 131 | } |
| 132 | |
pavery | f4a08b3 | 2005-02-02 21:39:25 +0000 | [diff] [blame] | 133 | public String getPartitionType(IDocument doc, int offset) { |
david_williams | d6ee069 | 2005-02-23 16:38:05 +0000 | [diff] [blame] | 134 | ITypedRegion tr = getPartition(doc, offset); |
pavery | b0f98c5 | 2006-02-13 20:19:39 +0000 | [diff] [blame] | 135 | return (tr != null) ? tr.getType() : IStructuredPartitions.UNKNOWN_PARTITION; |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 136 | } |
| 137 | |
| 138 | public String[] getPartitionTypes() { |
| 139 | // using hash set to automatically get rid of dupes |
| 140 | HashSet tempResults = new HashSet(); |
| 141 | // add these partition types |
| 142 | tempResults.addAll(fPartitionTypes); |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 143 | return (String[]) tempResults.toArray(new String[tempResults.size()]); |
| 144 | } |
| 145 | |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 146 | protected IStructuredDocument getStructuredDocument() { |
| 147 | IStructuredDocument sDoc = null; |
| 148 | IDocument doc = getDocument(); |
| 149 | if (doc instanceof IStructuredDocument) |
| 150 | sDoc = (IStructuredDocument) getDocument(); |
| 151 | return sDoc; |
| 152 | } |
| 153 | |
| 154 | /** |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 155 | * Removes duplicates. |
| 156 | * |
| 157 | * @param results1 |
| 158 | * @param results2 |
| 159 | * @return |
| 160 | */ |
| 161 | protected IReconcileResult[] merge(IReconcileResult[] results1, IReconcileResult[] results2) { |
| 162 | if (results1 == null) |
| 163 | return results2; |
| 164 | if (results2 == null) |
| 165 | return results1; |
| 166 | |
| 167 | List results = new ArrayList(); |
| 168 | results.addAll(Arrays.asList(results1)); |
| 169 | for (int i = 0; i < results2.length; i++) { |
pavery | f4a08b3 | 2005-02-02 21:39:25 +0000 | [diff] [blame] | 170 | results.add(results2[i]); |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 171 | } |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 172 | return (IReconcileResult[]) results.toArray(new IReconcileResult[results.size()]); |
| 173 | } |
| 174 | |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 175 | /* |
| 176 | * (non-Javadoc) |
| 177 | * |
| 178 | * @see org.eclipse.jface.text.reconciler.AbstractReconcileStep#reconcileModel(org.eclipse.jface.text.reconciler.DirtyRegion, |
| 179 | * org.eclipse.jface.text.IRegion) |
| 180 | */ |
| 181 | protected IReconcileResult[] reconcileModel(DirtyRegion dirtyRegion, IRegion subRegion) { |
| 182 | return EMPTY_RECONCILE_RESULT_SET; |
| 183 | } |
| 184 | |
| 185 | /** |
| 186 | * Release resources used by the step here as needed. Be sure to call |
| 187 | * super.release() when you override this method as to propagate the |
| 188 | * release through all steps. |
| 189 | */ |
| 190 | public void release() { |
pavery | 3b75d5d | 2005-11-10 02:27:12 +0000 | [diff] [blame] | 191 | // |
david_williams | cfdb2cd | 2004-11-11 08:37:49 +0000 | [diff] [blame] | 192 | } |
amywu | ecebb04 | 2007-04-10 20:07:35 +0000 | [diff] [blame] | 193 | } |