XML Schema for layout configurations.
The only changes to the original XML sample: - the root element is called "layout-configs" (plural for container). - the <default> and <config> elements must be defined in that order: - 0..1 of <default> folowed by - 1..n of <config> It's invalid for the <device> node to be empty. default/config are defined by a <xsd:sequence>, which imposes the strict ordering. At first I used an <xsd:choice> which does not impose any ordering but then it becomes possible to define an empty <device> element. I'd rather live with the strict ordering (which also makes sense anyway) and enforce non-empty <device> elements in the schema. BUG 2138329 Change-Id: I581afb1d72825ae79df00d81c74c80a2a18680ad
This commit is contained in:
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
|
||||||
|
*
|
||||||
|
* 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.android.ide.eclipse.adt.internal.sdk;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public constants for the sdk-repository XML Schema.
|
||||||
|
*/
|
||||||
|
public class LayoutConfigsXsd {
|
||||||
|
|
||||||
|
/** The XML namespace of the layout-configs XML. */
|
||||||
|
public static final String NS_LAYOUT_CONFIG_XSD =
|
||||||
|
"http://schemas.android.com/sdk/android/layout-configs/1"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "layout-configs" element is the root element of this schema.
|
||||||
|
*
|
||||||
|
* It must contain one or more "device" elements that each define the configurations
|
||||||
|
* available for a given device.
|
||||||
|
*
|
||||||
|
* These definitions are used in the Graphical Layout Editor in the
|
||||||
|
* Android Development Tools (ADT) plugin for Eclipse.
|
||||||
|
*/
|
||||||
|
public static final String NODE_LAYOUT_CONFIGS = "layout-configs"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A device element must contain at most one "default" element followed
|
||||||
|
* by one or more ""config" elements.
|
||||||
|
*
|
||||||
|
* The "default" element defines all the default parameters inherited
|
||||||
|
* by the following "config" elements. Each "config" element can override
|
||||||
|
* the default values, if any.
|
||||||
|
*
|
||||||
|
* A "device" element also has a required "name" attribute that represents
|
||||||
|
* the user-interface name of this device.
|
||||||
|
*/
|
||||||
|
public static final String NODE_DEVICE = "device"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "default" element contains zero or more of all the parameter elements
|
||||||
|
* listed below. It defines all the parameters that are common to all
|
||||||
|
* declared "config" elements.
|
||||||
|
*/
|
||||||
|
public static final String NODE_DEFAULT = "default"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "config" element contains zero or more of all the parameter elements
|
||||||
|
* listed below. The parameters from the "default" element (if present) are
|
||||||
|
* automatically inherited and can be overridden.
|
||||||
|
*/
|
||||||
|
public static final String NODE_CONFIG = "config"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
|
||||||
|
public static final String NODE_SCREEN_SIZE = "screen-size"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String NODE_SCREEN_RATIO = "screen-ratio"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String NODE_SCREEN_ORIENTATION = "screen-orientation"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String NODE_PIXEL_DENSITY = "pixel-density"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String NODE_TOUCH_TYPE = "touch-type"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String NODE_KEYBOARD_STATE = "keyboard-state"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String NODE_TEXT_INPUT_METHOD = "text-input-method"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String NODE_NAV_METHOD = "nav-method"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String NODE_SCREEN_DIMENSION = "screen-dimension"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static final String NODE_SIZE = "size"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "name" attribute, used by both the "device" and the "config"
|
||||||
|
* elements. It represents the user-interface name of these objects.
|
||||||
|
*/
|
||||||
|
public static final String ATTR_NAME = "name"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to get an input stream of the layout config XML schema.
|
||||||
|
*/
|
||||||
|
public static InputStream getXsdStream() {
|
||||||
|
return LayoutConfigsXsd.class.getResourceAsStream("layout-configs.xsd"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
-->
|
||||||
|
<xsd:schema
|
||||||
|
targetNamespace="http://schemas.android.com/sdk/android/layout-configs/1"
|
||||||
|
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||||
|
xmlns:c="http://schemas.android.com/sdk/android/layout-configs/1"
|
||||||
|
elementFormDefault="qualified"
|
||||||
|
attributeFormDefault="unqualified"
|
||||||
|
version="1">
|
||||||
|
|
||||||
|
<xsd:element name="layout-configs">
|
||||||
|
<xsd:annotation>
|
||||||
|
<xsd:documentation>
|
||||||
|
The "layout-configs" element is the root element of this schema.
|
||||||
|
|
||||||
|
It must contain one or more "device" elements that each define the configurations
|
||||||
|
available for a given device.
|
||||||
|
|
||||||
|
These definitions are used in the Graphical Layout Editor in the
|
||||||
|
Android Development Tools (ADT) plugin for Eclipse.
|
||||||
|
</xsd:documentation>
|
||||||
|
</xsd:annotation>
|
||||||
|
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<!-- layout-configs defines a sequence of 1..n device elements. -->
|
||||||
|
<xsd:element name="device" minOccurs="1" maxOccurs="unbounded">
|
||||||
|
|
||||||
|
<xsd:annotation>
|
||||||
|
<xsd:documentation>
|
||||||
|
A device element must contain at most one "default" element
|
||||||
|
followed by one or more "config" elements.
|
||||||
|
|
||||||
|
The "default" element defines all the default parameters
|
||||||
|
inherited by the following "config" elements.
|
||||||
|
Each "config" element can override the default values, if any.
|
||||||
|
|
||||||
|
A "device" element also has a required "name" attribute that
|
||||||
|
represents the user-interface name of this device.
|
||||||
|
</xsd:documentation>
|
||||||
|
</xsd:annotation>
|
||||||
|
|
||||||
|
<xsd:complexType>
|
||||||
|
<!-- device defines a choice of 0..1 default element
|
||||||
|
and 1..n config elements. -->
|
||||||
|
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="default" type="c:parametersType"
|
||||||
|
minOccurs="0" maxOccurs="1" />
|
||||||
|
<xsd:element name="config" type="c:configType"
|
||||||
|
minOccurs="1" maxOccurs="unbounded" />
|
||||||
|
</xsd:sequence>
|
||||||
|
|
||||||
|
<xsd:attribute name="name" type="xsd:normalizedString" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:sequence>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
|
||||||
|
<!-- The type of a device>default element.
|
||||||
|
This is overridden by configType below for the device>config element.
|
||||||
|
-->
|
||||||
|
<xsd:complexType name="parametersType">
|
||||||
|
<xsd:annotation>
|
||||||
|
<xsd:documentation>
|
||||||
|
The parametersType define all the parameters that can happen either in a
|
||||||
|
"default" element or in a named "config" element.
|
||||||
|
Each parameter element can appear once at most.
|
||||||
|
</xsd:documentation>
|
||||||
|
</xsd:annotation>
|
||||||
|
|
||||||
|
<xsd:all>
|
||||||
|
<!-- parametersType says that 0..1 of each of these elements must be declared. -->
|
||||||
|
|
||||||
|
<xsd:element name="screen-size" minOccurs="0">
|
||||||
|
<xsd:simpleType>
|
||||||
|
<xsd:restriction base="xsd:token">
|
||||||
|
<xsd:enumeration value="small" />
|
||||||
|
<xsd:enumeration value="medium" />
|
||||||
|
<xsd:enumeration value="large" />
|
||||||
|
</xsd:restriction>
|
||||||
|
</xsd:simpleType>
|
||||||
|
</xsd:element>
|
||||||
|
|
||||||
|
<xsd:element name="screen-ratio" minOccurs="0">
|
||||||
|
<xsd:simpleType>
|
||||||
|
<xsd:restriction base="xsd:token">
|
||||||
|
<xsd:enumeration value="long" />
|
||||||
|
<xsd:enumeration value="notlong" />
|
||||||
|
</xsd:restriction>
|
||||||
|
</xsd:simpleType>
|
||||||
|
</xsd:element>
|
||||||
|
|
||||||
|
<xsd:element name="screen-orientation" minOccurs="0">
|
||||||
|
<xsd:simpleType>
|
||||||
|
<xsd:restriction base="xsd:token">
|
||||||
|
<xsd:enumeration value="port" />
|
||||||
|
<xsd:enumeration value="land" />
|
||||||
|
<xsd:enumeration value="square" />
|
||||||
|
</xsd:restriction>
|
||||||
|
</xsd:simpleType>
|
||||||
|
</xsd:element>
|
||||||
|
|
||||||
|
<xsd:element name="pixel-density" minOccurs="0">
|
||||||
|
<xsd:simpleType>
|
||||||
|
<xsd:restriction base="xsd:token">
|
||||||
|
<xsd:enumeration value="ldpi" />
|
||||||
|
<xsd:enumeration value="mdpi" />
|
||||||
|
<xsd:enumeration value="hdpi" />
|
||||||
|
</xsd:restriction>
|
||||||
|
</xsd:simpleType>
|
||||||
|
</xsd:element>
|
||||||
|
|
||||||
|
<xsd:element name="touch-type" minOccurs="0">
|
||||||
|
<xsd:simpleType>
|
||||||
|
<xsd:restriction base="xsd:token">
|
||||||
|
<xsd:enumeration value="notouch" />
|
||||||
|
<xsd:enumeration value="stylus" />
|
||||||
|
<xsd:enumeration value="finger" />
|
||||||
|
</xsd:restriction>
|
||||||
|
</xsd:simpleType>
|
||||||
|
</xsd:element>
|
||||||
|
|
||||||
|
<xsd:element name="keyboard-state" minOccurs="0">
|
||||||
|
<xsd:simpleType>
|
||||||
|
<xsd:restriction base="xsd:token">
|
||||||
|
<xsd:enumeration value="keysexposed" />
|
||||||
|
<xsd:enumeration value="keyshidden" />
|
||||||
|
<xsd:enumeration value="keyssoft" />
|
||||||
|
</xsd:restriction>
|
||||||
|
</xsd:simpleType>
|
||||||
|
</xsd:element>
|
||||||
|
|
||||||
|
<xsd:element name="text-input-method" minOccurs="0">
|
||||||
|
<xsd:simpleType>
|
||||||
|
<xsd:restriction base="xsd:token">
|
||||||
|
<xsd:enumeration value="nokeys" />
|
||||||
|
<xsd:enumeration value="qwerty" />
|
||||||
|
<xsd:enumeration value="12key" />
|
||||||
|
</xsd:restriction>
|
||||||
|
</xsd:simpleType>
|
||||||
|
</xsd:element>
|
||||||
|
|
||||||
|
<xsd:element name="nav-method" minOccurs="0">
|
||||||
|
<xsd:simpleType>
|
||||||
|
<xsd:restriction base="xsd:token">
|
||||||
|
<xsd:enumeration value="dpad" />
|
||||||
|
<xsd:enumeration value="trackball" />
|
||||||
|
<xsd:enumeration value="wheel" />
|
||||||
|
<xsd:enumeration value="nonav" />
|
||||||
|
</xsd:restriction>
|
||||||
|
</xsd:simpleType>
|
||||||
|
</xsd:element>
|
||||||
|
|
||||||
|
<xsd:element name="screen-dimension" minOccurs="0">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence minOccurs="2" maxOccurs="2">
|
||||||
|
|
||||||
|
<xsd:element name="size">
|
||||||
|
<xsd:simpleType>
|
||||||
|
<xsd:restriction base="xsd:positiveInteger" />
|
||||||
|
</xsd:simpleType>
|
||||||
|
</xsd:element>
|
||||||
|
|
||||||
|
</xsd:sequence>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:all>
|
||||||
|
</xsd:complexType>
|
||||||
|
|
||||||
|
<!-- The type definition of a device>config element.
|
||||||
|
This type is basically all the element defined by parametersType and an extra
|
||||||
|
required "name" attribute for the user-interface configuration name.
|
||||||
|
-->
|
||||||
|
<xsd:complexType name="configType">
|
||||||
|
<xsd:annotation>
|
||||||
|
<xsd:documentation>
|
||||||
|
The configType defines the content of a "config" element in a "device" element.
|
||||||
|
|
||||||
|
A "config" element can have all the parameters elements defined by
|
||||||
|
"parameterType". It also has a required "name" attribute that indicates the
|
||||||
|
user-interface name for this configuration.
|
||||||
|
</xsd:documentation>
|
||||||
|
</xsd:annotation>
|
||||||
|
|
||||||
|
<xsd:complexContent>
|
||||||
|
<xsd:extension base="c:parametersType">
|
||||||
|
<xsd:attribute name="name" type="xsd:normalizedString" use="required" />
|
||||||
|
</xsd:extension>
|
||||||
|
</xsd:complexContent>
|
||||||
|
</xsd:complexType>
|
||||||
|
|
||||||
|
</xsd:schema>
|
||||||
@@ -0,0 +1,303 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
|
||||||
|
*
|
||||||
|
* 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.android.ide.eclipse.adt.internal.sdk;
|
||||||
|
|
||||||
|
import org.xml.sax.ErrorHandler;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xml.sax.SAXParseException;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
import javax.xml.XMLConstants;
|
||||||
|
import javax.xml.transform.Source;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
import javax.xml.validation.Schema;
|
||||||
|
import javax.xml.validation.SchemaFactory;
|
||||||
|
import javax.xml.validation.Validator;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests local validation of a Layout-Configs sample XMLs using an XML Schema validator.
|
||||||
|
*/
|
||||||
|
public class TestLayoutConfisXsd extends TestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tearDown() throws Exception {
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A SAX error handler that captures the errors and warnings.
|
||||||
|
* This allows us to capture *all* errors and just not get an exception on the first one.
|
||||||
|
*/
|
||||||
|
private static class CaptureErrorHandler implements ErrorHandler {
|
||||||
|
|
||||||
|
private String mWarnings = "";
|
||||||
|
private String mErrors = "";
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public String getErrors() {
|
||||||
|
return mErrors;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public String getWarnings() {
|
||||||
|
return mWarnings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies if the handler captures some errors or warnings.
|
||||||
|
* Prints them on stderr.
|
||||||
|
* Also fails the unit test if any error was generated.
|
||||||
|
*/
|
||||||
|
public void verify() {
|
||||||
|
if (mWarnings.length() > 0) {
|
||||||
|
System.err.println(mWarnings);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mErrors.length() > 0) {
|
||||||
|
System.err.println(mErrors);
|
||||||
|
fail(mErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws SAXException
|
||||||
|
*/
|
||||||
|
public void error(SAXParseException ex) throws SAXException {
|
||||||
|
mErrors += "Error: " + ex.getMessage() + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws SAXException
|
||||||
|
*/
|
||||||
|
public void fatalError(SAXParseException ex) throws SAXException {
|
||||||
|
mErrors += "Fatal Error: " + ex.getMessage() + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws SAXException
|
||||||
|
*/
|
||||||
|
public void warning(SAXParseException ex) throws SAXException {
|
||||||
|
mWarnings += "Warning: " + ex.getMessage() + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Helpers ------------
|
||||||
|
|
||||||
|
/** Helper method that returns a validator for our XSD */
|
||||||
|
private Validator getValidator(CaptureErrorHandler handler) throws SAXException {
|
||||||
|
InputStream xsdStream = LayoutConfigsXsd.getXsdStream();
|
||||||
|
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
||||||
|
Schema schema = factory.newSchema(new StreamSource(xsdStream));
|
||||||
|
Validator validator = schema.newValidator();
|
||||||
|
if (handler != null) {
|
||||||
|
validator.setErrorHandler(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
return validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Validate a valid sample using an InputStream */
|
||||||
|
public void testValidateLocalRepositoryFile() throws Exception {
|
||||||
|
|
||||||
|
InputStream xmlStream =
|
||||||
|
TestLayoutConfisXsd.class.getResourceAsStream("config_sample.xml");
|
||||||
|
Source source = new StreamSource(xmlStream);
|
||||||
|
|
||||||
|
CaptureErrorHandler handler = new CaptureErrorHandler();
|
||||||
|
Validator validator = getValidator(handler);
|
||||||
|
validator.validate(source);
|
||||||
|
handler.verify();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An helper that validates a string against an expected regexp. */
|
||||||
|
private void assertRegex(String expectedRegexp, String actualString) {
|
||||||
|
assertNotNull(actualString);
|
||||||
|
assertTrue(
|
||||||
|
String.format("Regexp Assertion Failed:\nExpected: %s\nActual: %s\n",
|
||||||
|
expectedRegexp, actualString),
|
||||||
|
actualString.matches(expectedRegexp));
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Tests ------------
|
||||||
|
|
||||||
|
/** A document should at least have a root to be valid */
|
||||||
|
public void testEmptyXml() throws Exception {
|
||||||
|
String document = "<?xml version=\"1.0\"?>";
|
||||||
|
|
||||||
|
Source source = new StreamSource(new StringReader(document));
|
||||||
|
|
||||||
|
CaptureErrorHandler handler = new CaptureErrorHandler();
|
||||||
|
Validator validator = getValidator(handler);
|
||||||
|
|
||||||
|
try {
|
||||||
|
validator.validate(source);
|
||||||
|
} catch (SAXParseException e) {
|
||||||
|
// We expect to get this specific exception message
|
||||||
|
assertRegex("Premature end of file.*", e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// We shouldn't get here
|
||||||
|
handler.verify();
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A document with an unknown element. */
|
||||||
|
public void testUnknownContentXml() throws Exception {
|
||||||
|
String document = "<?xml version=\"1.0\"?>" +
|
||||||
|
"<d:layout-configs xmlns:d=\"http://schemas.android.com/sdk/android/layout-configs/1\" >" +
|
||||||
|
"<d:unknown />" +
|
||||||
|
"</d:layout-configs>";
|
||||||
|
|
||||||
|
Source source = new StreamSource(new StringReader(document));
|
||||||
|
|
||||||
|
// don't capture the validator errors, we want it to fail and catch the exception
|
||||||
|
Validator validator = getValidator(null);
|
||||||
|
try {
|
||||||
|
validator.validate(source);
|
||||||
|
} catch (SAXParseException e) {
|
||||||
|
// We expect a parse expression referring to this grammar rule
|
||||||
|
assertRegex("cvc-complex-type.2.4.a: Invalid content was found.*", e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If we get here, the validator has not failed as we expected it to.
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A document with an missing attribute in a device element. */
|
||||||
|
public void testIncompleteContentXml() throws Exception {
|
||||||
|
String document = "<?xml version=\"1.0\"?>" +
|
||||||
|
"<d:layout-configs xmlns:d=\"http://schemas.android.com/sdk/android/layout-configs/1\" >" +
|
||||||
|
"<d:device />" +
|
||||||
|
"</d:layout-configs>";
|
||||||
|
|
||||||
|
Source source = new StreamSource(new StringReader(document));
|
||||||
|
|
||||||
|
// don't capture the validator errors, we want it to fail and catch the exception
|
||||||
|
Validator validator = getValidator(null);
|
||||||
|
try {
|
||||||
|
validator.validate(source);
|
||||||
|
} catch (SAXParseException e) {
|
||||||
|
// We expect a parse error referring to this grammar rule
|
||||||
|
assertRegex("cvc-complex-type.4: Attribute 'name' must appear on element 'd:device'.", e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If we get here, the validator has not failed as we expected it to.
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A document with a root element containing no device element is not valid. */
|
||||||
|
public void testEmptyRootXml() throws Exception {
|
||||||
|
String document = "<?xml version=\"1.0\"?>" +
|
||||||
|
"<d:layout-configs xmlns:d=\"http://schemas.android.com/sdk/android/layout-configs/1\" />";
|
||||||
|
|
||||||
|
Source source = new StreamSource(new StringReader(document));
|
||||||
|
|
||||||
|
// don't capture the validator errors, we want it to fail and catch the exception
|
||||||
|
Validator validator = getValidator(null);
|
||||||
|
try {
|
||||||
|
validator.validate(source);
|
||||||
|
} catch (SAXParseException e) {
|
||||||
|
// We expect a parse expression referring to this grammar rule
|
||||||
|
assertRegex("cvc-complex-type.2.4.b: The content of element 'd:layout-configs' is not complete.*", e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If we get here, the validator has not failed as we expected it to.
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A document with an empty device element is not valid. */
|
||||||
|
public void testEmptyDeviceXml() throws Exception {
|
||||||
|
String document = "<?xml version=\"1.0\"?>" +
|
||||||
|
"<d:layout-configs xmlns:d=\"http://schemas.android.com/sdk/android/layout-configs/1\" >" +
|
||||||
|
"<d:device name=\"foo\"/>" +
|
||||||
|
"</d:layout-configs>";
|
||||||
|
|
||||||
|
Source source = new StreamSource(new StringReader(document));
|
||||||
|
|
||||||
|
// don't capture the validator errors, we want it to fail and catch the exception
|
||||||
|
Validator validator = getValidator(null);
|
||||||
|
try {
|
||||||
|
validator.validate(source);
|
||||||
|
} catch (SAXParseException e) {
|
||||||
|
// We expect a parse error referring to this grammar rule
|
||||||
|
assertRegex("cvc-complex-type.2.4.b: The content of element 'd:device' is not complete.*", e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If we get here, the validator has not failed as we expected it to.
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A document with two default elements in a device element is not valid. */
|
||||||
|
public void testTwoDefaultsXml() throws Exception {
|
||||||
|
String document = "<?xml version=\"1.0\"?>" +
|
||||||
|
"<d:layout-configs xmlns:d=\"http://schemas.android.com/sdk/android/layout-configs/1\" >" +
|
||||||
|
"<d:device name=\"foo\">" +
|
||||||
|
" <d:default />" +
|
||||||
|
" <d:default />" +
|
||||||
|
"</d:device>" +
|
||||||
|
"</d:layout-configs>";
|
||||||
|
|
||||||
|
Source source = new StreamSource(new StringReader(document));
|
||||||
|
|
||||||
|
// don't capture the validator errors, we want it to fail and catch the exception
|
||||||
|
Validator validator = getValidator(null);
|
||||||
|
try {
|
||||||
|
validator.validate(source);
|
||||||
|
} catch (SAXParseException e) {
|
||||||
|
// We expect a parse error referring to this grammar rule
|
||||||
|
assertRegex("cvc-complex-type.2.4.a: Invalid content was found starting with element 'd:default'.*", e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If we get here, the validator has not failed as we expected it to.
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The default elements must be defined before the config one. It's invalid if after. */
|
||||||
|
public void testDefaultConfigOrderXml() throws Exception {
|
||||||
|
String document = "<?xml version=\"1.0\"?>" +
|
||||||
|
"<d:layout-configs xmlns:d=\"http://schemas.android.com/sdk/android/layout-configs/1\" >" +
|
||||||
|
"<d:device name=\"foo\">" +
|
||||||
|
" <d:config name=\"must-be-after-default\" />" +
|
||||||
|
" <d:default />" +
|
||||||
|
"</d:device>" +
|
||||||
|
"</d:layout-configs>";
|
||||||
|
|
||||||
|
Source source = new StreamSource(new StringReader(document));
|
||||||
|
|
||||||
|
// don't capture the validator errors, we want it to fail and catch the exception
|
||||||
|
Validator validator = getValidator(null);
|
||||||
|
try {
|
||||||
|
validator.validate(source);
|
||||||
|
} catch (SAXParseException e) {
|
||||||
|
// We expect a parse error referring to this grammar rule
|
||||||
|
assertRegex("cvc-complex-type.2.4.a: Invalid content was found starting with element 'd:default'.*", e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If we get here, the validator has not failed as we expected it to.
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
-->
|
||||||
|
<d:layout-configs
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:d="http://schemas.android.com/sdk/android/layout-configs/1">
|
||||||
|
|
||||||
|
<d:device name="MyDevice"> <!-- 1..n -->
|
||||||
|
<d:default> <!-- 0..1 -->
|
||||||
|
<d:screen-size>small</d:screen-size>
|
||||||
|
<d:screen-ratio>long</d:screen-ratio>
|
||||||
|
<d:screen-orientation>port</d:screen-orientation>
|
||||||
|
<d:pixel-density>ldpi</d:pixel-density>
|
||||||
|
<d:touch-type>notouch</d:touch-type>
|
||||||
|
<d:keyboard-state>keysexposed</d:keyboard-state>
|
||||||
|
<d:text-input-method>nokeys</d:text-input-method>
|
||||||
|
<d:nav-method>dpad</d:nav-method>
|
||||||
|
<d:screen-dimension>
|
||||||
|
<d:size>240</d:size> <!-- 2 * int>0 -->
|
||||||
|
<d:size>480</d:size>
|
||||||
|
</d:screen-dimension>
|
||||||
|
</d:default>
|
||||||
|
|
||||||
|
<d:config name="Portrait">
|
||||||
|
<d:keyboard-state>keyshidden</d:keyboard-state>
|
||||||
|
<d:screen-orientation>port</d:screen-orientation>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="Landscape, closed">
|
||||||
|
<d:keyboard-state>keyshidden</d:keyboard-state>
|
||||||
|
<d:screen-orientation>land</d:screen-orientation>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="Landscape, open">
|
||||||
|
<d:keyboard-state>keysexposed</d:keyboard-state>
|
||||||
|
<d:screen-orientation>land</d:screen-orientation>
|
||||||
|
</d:config>
|
||||||
|
|
||||||
|
<d:config name="screen-size-small">
|
||||||
|
<d:screen-size>small</d:screen-size>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="screen-size-medium">
|
||||||
|
<d:screen-size>medium</d:screen-size>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="screen-size-large">
|
||||||
|
<d:screen-size>large</d:screen-size>
|
||||||
|
</d:config>
|
||||||
|
|
||||||
|
<d:config name="screen-ratio-long">
|
||||||
|
<d:screen-ratio>long</d:screen-ratio>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="screen-ratio-notlong">
|
||||||
|
<d:screen-ratio>notlong</d:screen-ratio>
|
||||||
|
</d:config>
|
||||||
|
|
||||||
|
<d:config name="screen-orientation-port">
|
||||||
|
<d:screen-orientation>port</d:screen-orientation>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="screen-orientation-land">
|
||||||
|
<d:screen-orientation>land</d:screen-orientation>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="screen-orientation-square">
|
||||||
|
<d:screen-orientation>square</d:screen-orientation>
|
||||||
|
</d:config>
|
||||||
|
|
||||||
|
<d:config name="pixel-density-ldpi">
|
||||||
|
<d:pixel-density>ldpi</d:pixel-density>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="pixel-density-mdpi">
|
||||||
|
<d:pixel-density>mdpi</d:pixel-density>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="pixel-density-hdpi">
|
||||||
|
<d:pixel-density>hdpi</d:pixel-density>
|
||||||
|
</d:config>
|
||||||
|
|
||||||
|
<d:config name="touch-type-notouch">
|
||||||
|
<d:touch-type>notouch</d:touch-type>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="touch-type-stylus">
|
||||||
|
<d:touch-type>stylus</d:touch-type>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="touch-type-finger">
|
||||||
|
<d:touch-type>finger</d:touch-type>
|
||||||
|
</d:config>
|
||||||
|
|
||||||
|
<d:config name="text-input-method-nokeys">
|
||||||
|
<d:text-input-method>nokeys</d:text-input-method>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="text-input-method-qwerty">
|
||||||
|
<d:text-input-method>qwerty</d:text-input-method>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="text-input-method-12key">
|
||||||
|
<d:text-input-method>12key</d:text-input-method>
|
||||||
|
</d:config>
|
||||||
|
|
||||||
|
<d:config name="nav-method-dpad">
|
||||||
|
<d:nav-method>dpad</d:nav-method>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="nav-method-trackball">
|
||||||
|
<d:nav-method>trackball</d:nav-method>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="nav-method-wheel">
|
||||||
|
<d:nav-method>wheel</d:nav-method>
|
||||||
|
</d:config>
|
||||||
|
<d:config name="nav-method-nonav">
|
||||||
|
<d:nav-method>nonav</d:nav-method>
|
||||||
|
</d:config>
|
||||||
|
|
||||||
|
</d:device>
|
||||||
|
|
||||||
|
|
||||||
|
<d:device name="SomePhone"> <!-- 1..n -->
|
||||||
|
<d:config name="screen-size-medium">
|
||||||
|
<d:screen-size>medium</d:screen-size>
|
||||||
|
</d:config>
|
||||||
|
</d:device>
|
||||||
|
|
||||||
|
</d:layout-configs>
|
||||||
Reference in New Issue
Block a user