blob: 6c4484615744b7ea7ac7ee0a866c6eba338ec8c1 [file] [log] [blame]
david_williamscfdb2cd2004-11-11 08:37:49 +00001/*******************************************************************************
2 * Copyright (c) 2001, 2004 IBM Corporation and others.
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
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Jens Lukowski/Innoopract - initial renaming/restructuring
11 *
12 *******************************************************************************/
13package org.eclipse.wst.sse.ui.internal.reconcile.validator;
14
15import java.util.ArrayList;
16import java.util.Arrays;
17import java.util.HashMap;
pavery46c93e72005-02-08 16:07:33 +000018import java.util.HashSet;
david_williamscfdb2cd2004-11-11 08:37:49 +000019import java.util.Iterator;
20import java.util.List;
pavery46c93e72005-02-08 16:07:33 +000021import java.util.Set;
david_williamscfdb2cd2004-11-11 08:37:49 +000022
pavery46c93e72005-02-08 16:07:33 +000023import org.eclipse.core.runtime.Platform;
24import org.eclipse.core.runtime.content.IContentType;
25import org.eclipse.core.runtime.content.IContentTypeManager;
david_williamscfdb2cd2004-11-11 08:37:49 +000026import org.eclipse.jface.text.IDocument;
27import org.eclipse.jface.text.ITypedRegion;
28import org.eclipse.jface.text.reconciler.DirtyRegion;
29import org.eclipse.jface.text.reconciler.IReconcileResult;
30import org.eclipse.jface.text.reconciler.IReconcileStep;
nitindf8e77632005-09-07 23:49:25 +000031import org.eclipse.jface.text.source.ISourceViewer;
paveryb0763c02005-10-17 15:55:28 +000032import org.eclipse.wst.sse.ui.internal.IReleasable;
david_williamscfdb2cd2004-11-11 08:37:49 +000033import org.eclipse.wst.sse.ui.internal.reconcile.DocumentAdapter;
pavery1f1588d2006-02-15 20:44:54 +000034import org.eclipse.wst.sse.ui.internal.reconcile.ReconcileAnnotationKey;
paveryf4a08b32005-02-02 21:39:25 +000035import org.eclipse.wst.sse.ui.internal.reconcile.StructuredReconcileStep;
paverydc8b3062005-10-24 20:43:42 +000036import org.eclipse.wst.sse.ui.internal.reconcile.StructuredTextReconcilingStrategy;
david_williamscfdb2cd2004-11-11 08:37:49 +000037import org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation;
david_williams49d24fb2005-04-08 21:16:59 +000038import org.eclipse.wst.validation.internal.provisional.core.IValidator;
david_williamscfdb2cd2004-11-11 08:37:49 +000039
40
41/**
paveryf918eb22005-03-29 18:26:53 +000042 * Special validator strategy. Runs validator steps contributed via the
43 * <code>org.eclipse.wst.sse.ui.extensions.sourcevalidation</code> extension point
david_williamscfdb2cd2004-11-11 08:37:49 +000044 *
45 * @author pavery
46 */
paverydc8b3062005-10-24 20:43:42 +000047public class ValidatorStrategy extends StructuredTextReconcilingStrategy {
pavery46c93e72005-02-08 16:07:33 +000048
49 private String[] fContentTypeIds = null;
pavery55ae4472005-02-16 23:00:16 +000050 /** validator id (as declared in ext point) -> ReconcileStepForValidator **/
51 private HashMap fVidToVStepMap = null;
david_williamscfdb2cd2004-11-11 08:37:49 +000052 private List fMetaData = null;
53
nitindf8e77632005-09-07 23:49:25 +000054 public ValidatorStrategy(ISourceViewer sourceViewer, String contentType) {
55 super(sourceViewer);
david_williamscfdb2cd2004-11-11 08:37:49 +000056 fMetaData = new ArrayList();
pavery46c93e72005-02-08 16:07:33 +000057 fContentTypeIds = calculateParentContentTypeIds(contentType);
pavery55ae4472005-02-16 23:00:16 +000058 fVidToVStepMap = new HashMap();
david_williamscfdb2cd2004-11-11 08:37:49 +000059 }
60
pavery46c93e72005-02-08 16:07:33 +000061 /**
paverya389cae2005-02-11 16:23:22 +000062 * The content type passed in should be the most specific one.
63 * TODO: This exact method is also in ValidatorMetaData. Should be in a common place.
64 *
pavery46c93e72005-02-08 16:07:33 +000065 * @param contentType
66 * @return
67 */
68 private String[] calculateParentContentTypeIds(String contentTypeId) {
paveryefd06f02005-02-08 20:33:04 +000069
pavery46c93e72005-02-08 16:07:33 +000070 Set parentTypes = new HashSet();
71
paveryefd06f02005-02-08 20:33:04 +000072 IContentTypeManager ctManager = Platform.getContentTypeManager();
73 IContentType ct = ctManager.getContentType(contentTypeId);
74 String id = contentTypeId;
75
76 while(ct != null && id != null) {
77
pavery46c93e72005-02-08 16:07:33 +000078 parentTypes.add(id);
paveryefd06f02005-02-08 20:33:04 +000079 ct = ctManager.getContentType(id);
80 if(ct != null) {
81 IContentType baseType = ct.getBaseType();
82 id = (baseType != null) ? baseType.getId() : null;
pavery46c93e72005-02-08 16:07:33 +000083 }
84 }
pavery46c93e72005-02-08 16:07:33 +000085 return (String[])parentTypes.toArray(new String[parentTypes.size()]);
86 }
87
pavery46c93e72005-02-08 16:07:33 +000088 public void addValidatorMetaData(ValidatorMetaData vmd) {
david_williamscfdb2cd2004-11-11 08:37:49 +000089 fMetaData.add(vmd);
90 }
91
pavery46c93e72005-02-08 16:07:33 +000092 /**
93 *
94 * @param partitionType
95 * @return true if the strategy contains at least one ValidatorMetaData
96 * that says it can handle the partition type (for a given content type)
97 */
david_williamscfdb2cd2004-11-11 08:37:49 +000098 public boolean canValidatePartition(String partitionType) {
99 ValidatorMetaData vmd = null;
100 for (int i = 0; i < fMetaData.size(); i++) {
101 vmd = (ValidatorMetaData) fMetaData.get(i);
pavery46c93e72005-02-08 16:07:33 +0000102 if (vmd.canHandleParitionType(getContentTypeIds(), partitionType))
david_williamscfdb2cd2004-11-11 08:37:49 +0000103 return true;
104 }
105 return false;
106 }
pavery3b75d5d2005-11-10 02:27:12 +0000107
108 protected boolean canHandlePartition(String partition) {
109 return canValidatePartition(partition);
110 }
david_williamscfdb2cd2004-11-11 08:37:49 +0000111
112 /*
113 * so that removal will work properly
114 *
115 * @see org.eclipse.wst.sse.ui.reconcile.AbstractStructuredTextReconcilingStrategy#containsStep(org.eclipse.jface.text.reconciler.IReconcileStep)
116 */
117 protected boolean containsStep(IReconcileStep step) {
pavery55ae4472005-02-16 23:00:16 +0000118 return step != null ? fVidToVStepMap.values().contains(step) : false;
david_williamscfdb2cd2004-11-11 08:37:49 +0000119 }
120
121 /**
david_williams4ad020f2005-04-18 08:00:30 +0000122 * @see org.eclipse.wst.sse.ui.internal.provisional.reconcile.AbstractStructuredTextReconcilingStrategy#createReconcileSteps()
david_williamscfdb2cd2004-11-11 08:37:49 +0000123 */
124 public void createReconcileSteps() {
125 // do nothing, steps are created
126 }
pavery1f1588d2006-02-15 20:44:54 +0000127 /**
128 * All content types on which this ValidatorStrategy can run
129 * @return
130 */
pavery46c93e72005-02-08 16:07:33 +0000131 public String[] getContentTypeIds() {
132 return fContentTypeIds;
david_williamscfdb2cd2004-11-11 08:37:49 +0000133 }
134
135 /*
136 * so that removal will work properly
137 *
138 * @see org.eclipse.wst.sse.ui.reconcile.AbstractStructuredTextReconcilingStrategy#getPartitionTypes()
139 */
140 public String[] getPartitionTypes() {
141 List partitionTypes = new ArrayList();
pavery55ae4472005-02-16 23:00:16 +0000142 Iterator keys = fVidToVStepMap.keySet().iterator();
david_williamscfdb2cd2004-11-11 08:37:49 +0000143 String key = null;
144 while (keys.hasNext()) {
145 key = (String) keys.next();
pavery55ae4472005-02-16 23:00:16 +0000146 StructuredReconcileStep step = (StructuredReconcileStep) fVidToVStepMap.get(key);
david_williamscfdb2cd2004-11-11 08:37:49 +0000147 partitionTypes.addAll(Arrays.asList(step.getPartitionTypes()));
148 }
149 return (String[]) partitionTypes.toArray(new String[partitionTypes.size()]);
150 }
paverydfec4172005-11-09 21:42:30 +0000151 /**
152 * @param tr Partition of the region to reconcile.
153 * @param dr Dirty region representation of the typed region
154 */
pavery46c93e72005-02-08 16:07:33 +0000155 public void reconcile(ITypedRegion tr, DirtyRegion dr) {
paverybaf7e522005-07-07 20:44:14 +0000156
157 if(isCanceled())
158 return;
159
paverydfec4172005-11-09 21:42:30 +0000160 IDocument doc = getDocument();
david_williamscfdb2cd2004-11-11 08:37:49 +0000161 // for external files, this can be null
paverydfec4172005-11-09 21:42:30 +0000162 if (doc == null)
163 return;
164
165 String partitionType = tr.getType();
166 if (canValidatePartition(partitionType)) {
167 ValidatorMetaData vmd = null;
david_williamscfdb2cd2004-11-11 08:37:49 +0000168
paverydfec4172005-11-09 21:42:30 +0000169 // IReconcileResult[]
170 ArrayList annotationsToAdd = new ArrayList();
171 // loop all of the relevant validator meta data
172 // to find new annotations
173 for (int i = 0; i < fMetaData.size() && !isCanceled(); i++) {
174 vmd = (ValidatorMetaData) fMetaData.get(i);
175 if (vmd.canHandleParitionType(getContentTypeIds(), partitionType)) {
176 // get step for partition type
177 Object o = fVidToVStepMap.get(vmd.getValidatorId());
178 ReconcileStepForValidator validatorStep = null;
179 if (o != null) {
180 validatorStep = (ReconcileStepForValidator) o;
181 } else {
182 // if doesn't exist, create one
183 IValidator validator = vmd.createValidator();
184 validatorStep = new ReconcileStepForValidator(validator, vmd.getValidatorScope());
185 validatorStep.setInputModel(new DocumentAdapter(doc));
david_williamscfdb2cd2004-11-11 08:37:49 +0000186
paverydfec4172005-11-09 21:42:30 +0000187 fVidToVStepMap.put(vmd.getValidatorId(), validatorStep);
david_williamscfdb2cd2004-11-11 08:37:49 +0000188 }
paverydfec4172005-11-09 21:42:30 +0000189 annotationsToAdd.addAll(Arrays.asList(validatorStep.reconcile(dr, dr)));
david_williamscfdb2cd2004-11-11 08:37:49 +0000190 }
191 }
paverydfec4172005-11-09 21:42:30 +0000192
193 TemporaryAnnotation[] annotationsToRemove= getAnnotationsToRemove(dr);
194 if (annotationsToRemove.length + annotationsToAdd.size() > 0)
195 smartProcess(annotationsToRemove, (IReconcileResult[]) annotationsToAdd.toArray(new IReconcileResult[annotationsToAdd.size()]));
196
david_williamscfdb2cd2004-11-11 08:37:49 +0000197 }
198 }
199
pavery55ae4472005-02-16 23:00:16 +0000200 /**
david_williamscfdb2cd2004-11-11 08:37:49 +0000201 * @see org.eclipse.wst.sse.ui.internal.reconcile.AbstractStructuredTextReconcilingStrategy#setDocument(org.eclipse.jface.text.IDocument)
202 */
203 public void setDocument(IDocument document) {
paverydc8b3062005-10-24 20:43:42 +0000204
david_williamscfdb2cd2004-11-11 08:37:49 +0000205 super.setDocument(document);
paverydc8b3062005-10-24 20:43:42 +0000206
pavery55ae4472005-02-16 23:00:16 +0000207 // validator steps are in "fVIdToVStepMap" (as opposed to fFirstStep >
david_williamscfdb2cd2004-11-11 08:37:49 +0000208 // next step etc...)
pavery55ae4472005-02-16 23:00:16 +0000209 Iterator it = fVidToVStepMap.values().iterator();
david_williamscfdb2cd2004-11-11 08:37:49 +0000210 IReconcileStep step = null;
211 while (it.hasNext()) {
212 step = (IReconcileStep) it.next();
213 step.setInputModel(new DocumentAdapter(document));
214 }
215 }
paverybaf7e522005-07-07 20:44:14 +0000216
paveryb0763c02005-10-17 15:55:28 +0000217 public void release() {
218 super.release();
219 Iterator it = fVidToVStepMap.values().iterator();
220 IReconcileStep step = null;
221 while (it.hasNext()) {
222 step = (IReconcileStep) it.next();
223 if(step instanceof IReleasable)
224 ((IReleasable)step).release();
225 }
226 }
pavery1f1588d2006-02-15 20:44:54 +0000227 /**
228 *
229 * @param partitionType
230 * @return true if all validators associated with this
231 * parition type are total scope, otherwise return false
232 */
233 public boolean allTotalScope(String partitionType) {
234 Iterator vmds = fMetaData.iterator();
235 while(vmds.hasNext()) {
236 ValidatorMetaData vmd = (ValidatorMetaData)vmds.next();
237 if(vmd.canHandleParitionType(getContentTypeIds(), partitionType)) {
238 if(vmd.getValidatorScope() == ReconcileAnnotationKey.PARTIAL)
239 return false;
240 }
241 }
242 return true;
243 }
paveryb0763c02005-10-17 15:55:28 +0000244
paverybaf7e522005-07-07 20:44:14 +0000245 public boolean isTotalScope() {
246 return true;
247 }
david_williamscfdb2cd2004-11-11 08:37:49 +0000248}