1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 /*
24  * Created on 2005
25  *	by Christian Schmidt
26  */
27 package com.sun.star.tooling.DirtyTags;
28 
29 import java.io.IOException;
30 import java.util.ArrayList;
31 import java.util.Iterator;
32 
33 
34 /**
35  * @author Christian Schmidt 2005
36  *
37  */
38 public class TagPair {
39 
40 
41     private Tag startTag=Tag.EMPTYTAG;
42     private Tag endTag=Tag.EMPTYTAG;
43     private String startingText="";
44     private ArrayList enclosedTags=new ArrayList();
45     private long id;
46     private static int ElementCounter=1;
47     private String endingText="";
48 
49     /**
50      * @author Christian Schmidt 2005
51      *
52      */
53     public class TagPairConstructionException extends Exception {
54 
55         /**
56          * Create a new Instance of TagPairConstructionException
57          *
58          * @param string
59          */
TagPairConstructionException(String string)60         public TagPairConstructionException(String string) {
61 
62         }
63 
64     }
65 
66     /**
67      * Create a new Instance of TagPair
68      *
69      *
70      */
TagPair()71     public TagPair() {
72 
73     }
74 
75 
76     /**
77      * Create a new Instance of TagPair
78      *
79      * Find matching tags in tagList, create a TagPair of it, create
80      * tagPairs from the content in the tagPair and remove all used
81      * tags from tagList. The rest of the tagList starts after the
82      * endTag of this TagPair.
83      *
84      * @param tagList a List of the tags to check
85      *
86      * @throws TagPairConstructionException
87      */
TagPair(ArrayList tagList)88     public TagPair(ArrayList tagList) throws TagPairConstructionException {
89 
90         if(tagList.size()==0){
91             return;
92         }
93         ArrayList contentList=new ArrayList();;
94         Tag tag=(Tag)tagList.get(0);
95         tagList.remove(0);
96 
97 
98         if("Text".equals(tag.getTagType())){
99             // is this Text the only content
100             // of this Tag ?
101             if(tagList.size()==0){
102                 //yes...then it is the starting Text of this TagPair
103                 this.startingText=tag.getTagString();
104                 return;
105             }else{
106                 //no...the tag is normal content
107                 contentList.add(tag);
108             }
109            this.startingText=tag.getTagString();
110 
111         }else if("EndTag".equals(tag.getTagType())){
112             //ERRor throw EXception
113         }else if("StartTag".equals(tag.getTagType())){
114             // find the matching end tag
115             this.startTag=tag;
116             Iterator iter=tagList.iterator();
117 
118             int equivalentTagCounter=0;
119             while(iter.hasNext()){
120                 //is this the end tag?
121                 if((tag=(Tag)iter.next()).getTagName().equals('/'+this.startTag.getTagName())&&equivalentTagCounter==0){
122                     //found the corresponding end tag
123 
124                     //this TagPair is complete
125                     //so it needs an id
126                     this.id=TagPair.ElementCounter++;
127                     this.endTag=tag;
128                     //...remove it from list
129                     tagList.removeAll(contentList);
130                     tagList.remove(tag);
131                     break;
132                 }else{
133                     // tag is not the end tag
134                     // so it is between the start and the end tag
135                     // and belongs to the content
136                    // but first check if it has the same name as the current tag
137                     if(tag.getTagName().equals(this.startTag.getTagName())){
138                         // if this is a start tag like the current start tag
139                         // we count it to find out the matching end tag in nested tags
140                         if(tag.getTagType().equals("StartTag")){
141                             equivalentTagCounter++;
142                         }
143                     }
144                     if(tag.getTagName().equals("/"+this.startTag.getTagName())){
145                         if(tag.getTagType().equals("EndTag")){
146                             equivalentTagCounter--;
147                         }
148                     }
149 
150                     contentList.add(tag);
151                 }
152             }
153             //found the end tag ?
154             //no...
155             if (this.endTag.getTagType()==""){
156 
157                 throw new TagPairConstructionException("ERROR: Missing end tag ("+
158                         this.startTag.getTagString()+").");
159             //...yes
160             }else{
161                 //We need to check whether the content is starting or ending with text
162                 //...check starting with text
163                 if(contentList.size()>=1&&((String)((Tag)contentList.get(0)).getTagType()).equals("Text")){
164                     //yes...store it as startingText
165                     this.startingText=(String)((Tag)contentList.get(0)).getTagString();
166                     //remove it from list
167                     contentList.remove(0);
168                 }
169                 // ...check ending with text
170                 if(contentList.size()>=1&&((String)((Tag)contentList.get(contentList.size()-1)).getTagType()).equals("Text")){
171                     //yes...store it as endingText
172                     this.endingText=(String)((Tag)contentList.get(contentList.size()-1)).getTagString();
173                     //remove it from list
174                     contentList.remove(contentList.size()-1);
175                 }
176                 //create the list of tags enclosed by this tagPair
177                 createEnclosedTags(contentList);
178             }
179         //if stand AloneTag create own TagObject...give ID...add to List
180         }else if("StartAndEndTag".equals(tag.getTagType())){
181             this.startTag=tag;
182             this.endTag=new Tag("EndOfStandAlone","","");
183             createEnclosedTags(contentList);
184         }
185 
186     }
187 
188     /**
189      * @param contentList
190      * @throws TagPairConstructionException
191      */
createEnclosedTags(ArrayList contentList)192     private void createEnclosedTags(ArrayList contentList) throws TagPairConstructionException {
193         while(contentList.size()>0){
194             //create the inner TagPairs
195             this.enclosedTags.add(new TagPair(contentList));
196         }
197 
198     }
199 
toString()200     public String toString(){
201         StringBuffer outString= new StringBuffer(this.startTag.toString());
202         TagPair help=new TagPair();
203         Iterator iter=enclosedTags.iterator();
204         outString.append(this.startingText);
205         while(iter.hasNext()){
206             if((help=(TagPair)iter.next())==null){
207                 continue;
208             }else{
209                 outString.append(help.toString());
210             }
211         }
212         outString.append(this.endingText);
213         outString.append(this.endTag.toString());
214         return new String(outString);
215     }
216 
getWrapped()217     public String getWrapped() throws IOException{
218         Iterator iter=enclosedTags.iterator();
219         StringBuffer returnBuffer=new StringBuffer();
220 
221             returnBuffer.append(wrap(this.startTag)+xmlString(this.startingText));
222             while(iter.hasNext()){
223                 returnBuffer.append(((TagPair)iter.next()).getWrapped());
224             }
225             returnBuffer.append(xmlString(this.endingText)+wrap(this.endTag));
226 
227 
228 
229         return new String(returnBuffer);
230     }
231 
wrap(Tag tag)232     private String wrap(Tag tag) throws IOException{
233         String string="";
234         //can be a start tag
235         if(tag.getTagType().startsWith("Start")){
236             return new String("<bpt id='"+this.id+"'>"+tag.getWrappedTagString()+"</bpt>");
237         //...or a end tag
238         }else if (tag.getTagType().startsWith("End")){
239             //maybe the end tag of a Start and end tag
240 //            if("EndOfStandAlone".equals(tag.getTagType())){
241 //                return new String("<ex id='"+this.id+"'/>");
242 //            }else{
243                 string=tag.getWrappedTagString();
244                 return new String("<ept id='"+this.id+"'>"+string+"</ept>");
245 //            }
246 
247         //...or text
248         }else{
249             return xmlString(tag.getTagString());
250         }
251     }
252     /**
253      * Replaces all characters that mustn't be in XLIFF PCdata
254      *
255      * @param string the string to check
256      * @return the checked string with all characters replaced
257      * @throws java.io.IOException
258      */
xmlString( final String string)259     private final String xmlString( final String string) throws java.io.IOException {
260         if (string == null)
261             return string; // ""
262         String str = string;
263 
264          for(int i=0;i<str.length();i++){
265              if(str.charAt(i)=='&'){
266                  str=str.substring(0, i)+"&amp;"+str.substring(i+1);
267                  continue;
268              }
269 
270              if(str.charAt(i)=='<'){
271                  str=str.substring(0, i)+"&lt;"+str.substring(i+1);
272                  continue;
273              }
274 
275              if(str.charAt(i)=='>'){
276                  str=str.substring(0, i)+"&gt;"+str.substring(i+1);
277                  continue;
278              }
279 
280              if(str.charAt(i)=='"'){
281                  str=str.substring(0, i)+"&quot;"+str.substring(i+1);
282                  continue;
283              }
284 
285              if(str.charAt(i)=='\''){
286                  str=str.substring(0, i)+"&apos;"+str.substring(i+1);
287                  continue;
288              }
289          }
290 
291         return str;
292     }
293 
294     /**
295      *
296      */
resetCounter()297     public static void resetCounter() {
298         TagPair.ElementCounter=1;
299 
300     }
301 
302 
303 }
304