@@ -246,99 +246,79 @@ else if (!hasLength(pathContainer)) {
246
246
* <li>'{@code /docs/cvs/*.html}' and '{@code /docs/cvs/commit.html} -> '{@code commit.html}'</li>
247
247
* <li>'{@code /docs/**}' and '{@code /docs/cvs/commit} -> '{@code cvs/commit}'</li>
248
248
* </ul>
249
- * <p><b>Note:</b> Assumes that {@link #matches} returns {@code true} for
249
+ * <p><b>Notes:</b>
250
+ * <ul>
251
+ * <li>Assumes that {@link #matches} returns {@code true} for
250
252
* the same path but does <strong>not</strong> enforce this.
253
+ * <li>Duplicate occurrences of separators within the returned result are removed
254
+ * <li>Leading and trailing separators are removed from the returned result
255
+ * </ul>
251
256
* @param path a path that matches this pattern
252
257
* @return the subset of the path that is matched by pattern or "" if none
253
258
* of it is matched by pattern elements
254
259
*/
255
260
public PathContainer extractPathWithinPattern (PathContainer path ) {
261
+ List <Element > pathElements = path .elements ();
262
+ int pathElementsCount = pathElements .size ();
256
263
257
- // TODO: implement extractPathWithinPattern for PathContainer
258
-
259
- // TODO: align behavior with matchStartOfPath with regards to this:
260
- // As per the contract on {@link PathMatcher}, this method will trim leading/trailing
261
- // separators. It will also remove duplicate separators in the returned path.
262
-
263
- String result = extractPathWithinPattern (path .value ());
264
- return PathContainer .parsePath (result );
265
- }
266
-
267
- private String extractPathWithinPattern (String path ) {
268
- // assert this.matches(path)
264
+ int startIndex = 0 ;
265
+ // Find first path element that is not a separator or a literal (i.e. the first pattern based element)
269
266
PathElement elem = head ;
270
- int separatorCount = 0 ;
271
- boolean matchTheRest = false ;
272
-
273
- // Find first path element that is pattern based
274
267
while (elem != null ) {
275
- if (elem instanceof SeparatorPathElement || elem instanceof CaptureTheRestPathElement ||
276
- elem instanceof WildcardTheRestPathElement ) {
277
- separatorCount ++;
278
- if (elem instanceof WildcardTheRestPathElement || elem instanceof CaptureTheRestPathElement ) {
279
- matchTheRest = true ;
280
- }
281
- }
282
268
if (elem .getWildcardCount () != 0 || elem .getCaptureCount () != 0 ) {
283
269
break ;
284
270
}
285
271
elem = elem .next ;
272
+ startIndex ++;
286
273
}
287
-
288
274
if (elem == null ) {
289
- return "" ; // there is no pattern mapped section
290
- }
291
-
292
- // Now separatorCount indicates how many sections of the path to skip
293
- char [] pathChars = path .toCharArray ();
294
- int len = pathChars .length ;
295
- int pos = 0 ;
296
- while (separatorCount > 0 && pos < len ) {
297
- if (path .charAt (pos ++) == separator ) {
298
- separatorCount --;
299
- }
300
- }
301
- int end = len ;
302
- // Trim trailing separators
303
- if (!matchTheRest ) {
304
- while (end > 0 && path .charAt (end - 1 ) == separator ) {
305
- end --;
275
+ // There is no pattern piece
276
+ return PathContainer .parsePath ("" );
277
+ }
278
+
279
+ // Skip leading separators that would be in the result
280
+ while (startIndex < pathElementsCount && (pathElements .get (startIndex ) instanceof Separator )) {
281
+ startIndex ++;
282
+ }
283
+
284
+ int endIndex = pathElements .size ();
285
+ // Skip trailing separators that would be in the result
286
+ while (endIndex > 0 && (pathElements .get (endIndex - 1 ) instanceof Separator )) {
287
+ endIndex --;
288
+ }
289
+
290
+ boolean multipleAdjacentSeparators = false ;
291
+ for (int i = startIndex ; i < (endIndex - 1 ); i ++) {
292
+ if ((pathElements .get (i ) instanceof Separator ) && (pathElements .get (i +1 ) instanceof Separator )) {
293
+ multipleAdjacentSeparators =true ;
294
+ break ;
306
295
}
307
296
}
308
-
309
- // Check if multiple separators embedded in the resulting path, if so trim them out.
310
- // Example: aaa////bbb//ccc/d -> aaa/bbb/ccc/d
311
- // The stringWithDuplicateSeparatorsRemoved is only computed if necessary
312
- int c = pos ;
313
- StringBuilder stringWithDuplicateSeparatorsRemoved = null ;
314
- while (c < end ) {
315
- char ch = path .charAt (c );
316
- if (ch == separator ) {
317
- if ((c + 1 ) < end && path .charAt (c + 1 ) == separator ) {
318
- // multiple separators
319
- if (stringWithDuplicateSeparatorsRemoved == null ) {
320
- // first time seen, need to capture all data up to this point
321
- stringWithDuplicateSeparatorsRemoved = new StringBuilder ();
322
- stringWithDuplicateSeparatorsRemoved .append (path .substring (pos , c ));
323
- }
324
- do {
325
- c ++;
326
- } while ((c + 1 ) < end && path .charAt (c + 1 ) == separator );
297
+
298
+ PathContainer resultPath = null ;
299
+ if (multipleAdjacentSeparators ) {
300
+ // Need to rebuild the path without the duplicate adjacent separators
301
+ StringBuilder buf = new StringBuilder ();
302
+ int i = startIndex ;
303
+ while (i < endIndex ) {
304
+ Element e = pathElements .get (i ++);
305
+ buf .append (e .value ());
306
+ if (e instanceof Separator ) {
307
+ while (i < endIndex && (pathElements .get (i ) instanceof Separator )) {
308
+ i ++;
309
+ }
327
310
}
328
311
}
329
- if (stringWithDuplicateSeparatorsRemoved != null ) {
330
- stringWithDuplicateSeparatorsRemoved .append (ch );
331
- }
332
- c ++;
312
+ resultPath = PathContainer .parsePath (buf .toString ());
313
+ } else if (startIndex >= endIndex ) {
314
+ resultPath = PathContainer .parsePath ("" );
333
315
}
334
-
335
- if (stringWithDuplicateSeparatorsRemoved != null ) {
336
- return stringWithDuplicateSeparatorsRemoved .toString ();
316
+ else {
317
+ resultPath = path .subPath (startIndex , endIndex );
337
318
}
338
- return ( pos == len ? "" : path . substring ( pos , end )) ;
319
+ return resultPath ;
339
320
}
340
321
341
-
342
322
/**
343
323
* Compare this pattern with a supplied pattern: return -1,0,+1 if this pattern
344
324
* is more specific, the same or less specific than the supplied pattern.
0 commit comments