/* * Copyright (C) 2022 github.com/REAndroid * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.reandroid.xml; import com.reandroid.xml.parser.XMLSpanParser; import java.util.*; public class XMLSpannable implements Comparable{ private XMLElement mElement; private String mText; private List mSpanInfoList; private XMLSpannable(XMLElement element){ this.mElement=element; } public boolean isValid(){ List spanInfoList = getSpanInfoList(); if(spanInfoList.size()==0){ return false; } for(XMLSpanInfo spanInfo:spanInfoList){ if(spanInfo.end getSpanInfoList(){ if(mSpanInfoList==null){ buildSpanInfo(); } return mSpanInfoList; } private void buildSpanInfo(){ mSpanInfoList=new ArrayList<>(); StringBuilder builder=new StringBuilder(); buildSpanInfo(mElement, builder); mText=builder.toString(); mElement=null; } private void buildSpanInfo(XMLElement element, StringBuilder builder){ XMLSpanInfo info=null; for(XMLNode node:element.listSpannable()){ if(info!=null){ info.end=builder.length(); info=null; } if(node instanceof XMLText){ builder.append(((XMLText)node).getText()); continue; } XMLElement child = (XMLElement) node; info=new XMLSpanInfo( child.getSpannableText(), builder.length(), 0); mSpanInfoList.add(info); buildSpanInfo(child, builder); } if(info!=null){ info.end=builder.length(); } } @Override public int compareTo(XMLSpannable xmlSpannable) { return getText().compareTo(xmlSpannable.getText()); } public static XMLSpannable parse(String text){ if(!hasStyle(text)){ return null; } try { XMLSpannable spannable=new XMLSpannable(PARSER.parse(text)); if(spannable.isValid()){ return spannable; } } catch (Exception ignored) { } return null; } public static Set tagList(Collection spannableList){ Set results=new HashSet<>(); for(XMLSpannable xmlSpannable:spannableList){ for(XMLSpanInfo spanInfo: xmlSpannable.getSpanInfoList()){ results.add(spanInfo.tag); } } return results; } public static List toTextList(Collection spannableList){ List results=new ArrayList<>(spannableList.size()); for(XMLSpannable xmlSpannable:spannableList){ results.add(xmlSpannable.getText()); } return results; } public static void sort(List spannableList){ Comparator cmp=new Comparator() { @Override public int compare(XMLSpannable s1, XMLSpannable s2) { return s1.compareTo(s2); } }; spannableList.sort(cmp); } private static boolean hasStyle(String text){ if(text==null){ return false; } int i=text.indexOf('<'); if(i<0){ return false; } i=text.indexOf('>'); return i>1; } private static final XMLSpanParser PARSER=new XMLSpanParser(); }