1/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Licensed to the Apache Software Foundation (ASF) under one or more
7 * contributor license agreements.  See the NOTICE file distributed with
8 * this work for additional information regarding copyright ownership.
9 * The ASF licenses this file to You under the Apache License, Version 2.0
10 * (the "License"); you may not use this file except in compliance with
11 * the License.  You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22package com.sun.org.apache.xerces.internal.impl.xpath.regex;
23
24import java.text.CharacterIterator;
25
26/**
27 * An instance of this class has ranges captured in matching.
28 *
29 * @xerces.internal
30 *
31 * @see RegularExpression#matches(char[], int, int, Match)
32 * @see RegularExpression#matches(char[], Match)
33 * @see RegularExpression#matches(java.text.CharacterIterator, Match)
34 * @see RegularExpression#matches(java.lang.String, int, int, Match)
35 * @see RegularExpression#matches(java.lang.String, Match)
36 * @author TAMURA Kent <kent@trl.ibm.co.jp>
37 */
38public class Match implements Cloneable {
39    int[] beginpos = null;
40    int[] endpos = null;
41    int nofgroups = 0;
42
43    CharacterIterator ciSource = null;
44    String strSource = null;
45    char[] charSource = null;
46
47    /**
48     * Creates an instance.
49     */
50    public Match() {
51    }
52
53    /**
54     *
55     */
56    public synchronized Object clone() {
57        Match ma = new Match();
58        if (this.nofgroups > 0) {
59            ma.setNumberOfGroups(this.nofgroups);
60            if (this.ciSource != null)  ma.setSource(this.ciSource);
61            if (this.strSource != null)  ma.setSource(this.strSource);
62            for (int i = 0;  i < this.nofgroups;  i ++) {
63                ma.setBeginning(i, this.getBeginning(i));
64                ma.setEnd(i, this.getEnd(i));
65            }
66        }
67        return ma;
68    }
69
70    /**
71     *
72     */
73    protected void setNumberOfGroups(int n) {
74        int oldn = this.nofgroups;
75        this.nofgroups = n;
76        if (oldn <= 0
77            || oldn < n || n*2 < oldn) {
78            this.beginpos = new int[n];
79            this.endpos = new int[n];
80        }
81        for (int i = 0;  i < n;  i ++) {
82            this.beginpos[i] = -1;
83            this.endpos[i] = -1;
84        }
85    }
86
87    /**
88     *
89     */
90    protected void setSource(CharacterIterator ci) {
91        this.ciSource = ci;
92        this.strSource = null;
93        this.charSource = null;
94    }
95    /**
96     *
97     */
98    protected void setSource(String str) {
99        this.ciSource = null;
100        this.strSource = str;
101        this.charSource = null;
102    }
103    /**
104     *
105     */
106    protected void setSource(char[] chars) {
107        this.ciSource = null;
108        this.strSource = null;
109        this.charSource = chars;
110    }
111
112    /**
113     *
114     */
115    protected void setBeginning(int index, int v) {
116        this.beginpos[index] = v;
117    }
118
119    /**
120     *
121     */
122    protected void setEnd(int index, int v) {
123        this.endpos[index] = v;
124    }
125
126    /**
127     * Return the number of regular expression groups.
128     * This method returns 1 when the regular expression has no capturing-parenthesis.
129     */
130    public int getNumberOfGroups() {
131        if (this.nofgroups <= 0)
132            throw new IllegalStateException("A result is not set.");
133        return this.nofgroups;
134    }
135
136    /**
137     * Return a start position in the target text matched to specified regular expression group.
138     *
139     * @param index Less than <code>getNumberOfGroups()</code>.
140     */
141    public int getBeginning(int index) {
142        if (this.beginpos == null)
143            throw new IllegalStateException("A result is not set.");
144        if (index < 0 || this.nofgroups <= index)
145            throw new IllegalArgumentException("The parameter must be less than "
146                                               +this.nofgroups+": "+index);
147        return this.beginpos[index];
148    }
149
150    /**
151     * Return an end position in the target text matched to specified regular expression group.
152     *
153     * @param index Less than <code>getNumberOfGroups()</code>.
154     */
155    public int getEnd(int index) {
156        if (this.endpos == null)
157            throw new IllegalStateException("A result is not set.");
158        if (index < 0 || this.nofgroups <= index)
159            throw new IllegalArgumentException("The parameter must be less than "
160                                               +this.nofgroups+": "+index);
161        return this.endpos[index];
162    }
163
164    /**
165     * Return an substring of the target text matched to specified regular expression group.
166     *
167     * @param index Less than <code>getNumberOfGroups()</code>.
168     */
169    public String getCapturedText(int index) {
170        if (this.beginpos == null)
171            throw new IllegalStateException("match() has never been called.");
172        if (index < 0 || this.nofgroups <= index)
173            throw new IllegalArgumentException("The parameter must be less than "
174                                               +this.nofgroups+": "+index);
175        String ret;
176        int begin = this.beginpos[index], end = this.endpos[index];
177        if (begin < 0 || end < 0)  return null;
178        if (this.ciSource != null) {
179            ret = REUtil.substring(this.ciSource, begin, end);
180        } else if (this.strSource != null) {
181            ret = this.strSource.substring(begin, end);
182        } else {
183            ret = new String(this.charSource, begin, end-begin);
184        }
185        return ret;
186    }
187}
188