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)+"&"+str.substring(i+1); 267 continue; 268 } 269 270 if(str.charAt(i)=='<'){ 271 str=str.substring(0, i)+"<"+str.substring(i+1); 272 continue; 273 } 274 275 if(str.charAt(i)=='>'){ 276 str=str.substring(0, i)+">"+str.substring(i+1); 277 continue; 278 } 279 280 if(str.charAt(i)=='"'){ 281 str=str.substring(0, i)+"""+str.substring(i+1); 282 continue; 283 } 284 285 if(str.charAt(i)=='\''){ 286 str=str.substring(0, i)+"'"+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