1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.compatibility.common.tradefed.testtype; 17 18 import com.android.compatibility.common.util.TestFilter; 19 import com.android.tradefed.util.xml.AbstractXmlParser; 20 21 import org.kxml2.io.KXmlSerializer; 22 import org.xml.sax.Attributes; 23 import org.xml.sax.SAXException; 24 import org.xml.sax.helpers.DefaultHandler; 25 26 import java.io.IOException; 27 import java.io.OutputStream; 28 import java.util.ArrayList; 29 import java.util.Collections; 30 import java.util.HashSet; 31 import java.util.Set; 32 33 /** 34 * Container, parser, and generator of SubPlan info. 35 */ 36 public class SubPlan extends AbstractXmlParser implements ISubPlan { 37 38 private final Set<String> mIncludes; 39 private final Set<String> mExcludes; 40 41 private static final String ENCODING = "UTF-8"; 42 private static final String NS = null; // namespace used for XML serializer 43 private static final String VERSION_ATTR = "version"; 44 private static final String SUBPLAN_VERSION = "2.0"; 45 46 private static final String SUBPLAN_TAG = "SubPlan"; 47 private static final String ENTRY_TAG = "Entry"; 48 private static final String EXCLUDE_ATTR = "exclude"; 49 private static final String INCLUDE_ATTR = "include"; 50 private static final String ABI_ATTR = "abi"; 51 private static final String NAME_ATTR = "name"; 52 SubPlan()53 public SubPlan() { 54 mIncludes = new HashSet<String>(); 55 mExcludes = new HashSet<String>(); 56 } 57 58 /** 59 * {@inheritDoc} 60 */ 61 @Override addIncludeFilter(String filter)62 public void addIncludeFilter(String filter) { 63 mIncludes.add(filter); 64 } 65 66 /** 67 * {@inheritDoc} 68 */ 69 @Override addAllIncludeFilters(Set<String> filters)70 public void addAllIncludeFilters(Set<String> filters) { 71 mIncludes.addAll(filters); 72 } 73 74 /** 75 * {@inheritDoc} 76 */ 77 @Override addExcludeFilter(String filter)78 public void addExcludeFilter(String filter) { 79 mExcludes.add(filter); 80 } 81 82 /** 83 * {@inheritDoc} 84 */ 85 @Override addAllExcludeFilters(Set<String> filters)86 public void addAllExcludeFilters(Set<String> filters) { 87 mExcludes.addAll(filters); 88 } 89 90 /** 91 * {@inheritDoc} 92 */ 93 @Override getIncludeFilters()94 public Set<String> getIncludeFilters() { 95 return new HashSet<String>(mIncludes); 96 } 97 98 /** 99 * {@inheritDoc} 100 */ 101 @Override getExcludeFilters()102 public Set<String> getExcludeFilters() { 103 return new HashSet<String>(mExcludes); 104 } 105 106 /** 107 * {@inheritDoc} 108 */ 109 @Override clearExcludeFilters()110 public void clearExcludeFilters() { 111 mExcludes.clear(); 112 } 113 114 /** 115 * {@inheritDoc} 116 */ 117 @Override clearIncludeFilters()118 public void clearIncludeFilters() { 119 mIncludes.clear(); 120 } 121 122 /** 123 * {@inheritDoc} 124 */ 125 @Override serialize(OutputStream stream)126 public void serialize(OutputStream stream) throws IOException { 127 KXmlSerializer serializer = new KXmlSerializer(); 128 serializer.setOutput(stream, ENCODING); 129 serializer.startDocument(ENCODING, false); 130 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 131 serializer.startTag(NS, SUBPLAN_TAG); 132 serializer.attribute(NS, VERSION_ATTR, SUBPLAN_VERSION); 133 134 ArrayList<String> sortedIncludes = new ArrayList<String>(mIncludes); 135 ArrayList<String> sortedExcludes = new ArrayList<String>(mExcludes); 136 Collections.sort(sortedIncludes); 137 Collections.sort(sortedExcludes); 138 for (String include : sortedIncludes) { 139 serializer.startTag(NS, ENTRY_TAG); 140 serializer.attribute(NS, INCLUDE_ATTR, include); 141 serializer.endTag(NS, ENTRY_TAG); 142 } 143 for (String exclude : sortedExcludes) { 144 serializer.startTag(NS, ENTRY_TAG); 145 serializer.attribute(NS, EXCLUDE_ATTR, exclude); 146 serializer.endTag(NS, ENTRY_TAG); 147 } 148 149 serializer.endTag(NS, SUBPLAN_TAG); 150 serializer.endDocument(); 151 } 152 153 /** 154 * {@inheritDoc} 155 */ 156 @Override createXmlHandler()157 protected DefaultHandler createXmlHandler() { 158 return new EntryHandler(); 159 } 160 161 /** 162 * SAX callback object. Handles parsing data from the xml tags. 163 */ 164 private class EntryHandler extends DefaultHandler { 165 166 @Override startElement(String uri, String localName, String name, Attributes attributes)167 public void startElement(String uri, String localName, String name, Attributes attributes) 168 throws SAXException { 169 if (ENTRY_TAG.equals(localName)) { 170 String includeString = attributes.getValue(INCLUDE_ATTR); 171 String excludeString = attributes.getValue(EXCLUDE_ATTR); 172 if (includeString != null && excludeString != null) { 173 throw new IllegalArgumentException( 174 "Cannot specify include and exclude filter in the same element"); 175 } 176 String abiString = attributes.getValue(ABI_ATTR); 177 String nameString = attributes.getValue(NAME_ATTR); 178 179 if (excludeString == null) { 180 parseFilter(abiString, nameString, includeString, mIncludes); 181 } else { 182 parseFilter(abiString, nameString, excludeString, mExcludes); 183 } 184 } 185 } 186 parseFilter(String abi, String name, String filter, Set<String> filterSet)187 private void parseFilter(String abi, String name, String filter, Set<String> filterSet) { 188 if (name == null) { 189 // ignore name and abi attributes, 'filter' should contain all necessary parts 190 filterSet.add(filter); 191 } else { 192 // 'filter' is name of test. Build TestFilter and convert back to string 193 filterSet.add(new TestFilter(abi, name, filter).toString()); 194 } 195 } 196 } 197 } 198