001 package com.oxygenxml.validate.nvdl; 002 003 import com.thaiopensource.util.PropertyId; 004 import com.thaiopensource.util.PropertyMap; 005 import com.thaiopensource.util.PropertyMapBuilder; 006 import com.thaiopensource.validate.IncorrectSchemaException; 007 import com.thaiopensource.validate.Option; 008 import com.thaiopensource.validate.Schema; 009 import com.thaiopensource.validate.SchemaReader; 010 import com.thaiopensource.validate.ValidateProperty; 011 import com.thaiopensource.validate.auto.AutoSchemaReader; 012 import com.thaiopensource.validate.auto.SchemaFuture; 013 import com.thaiopensource.validate.auto.SchemaReceiver; 014 import com.thaiopensource.validate.auto.SchemaReceiverFactory; 015 import com.thaiopensource.validate.rng.CompactSchemaReader; 016 import com.thaiopensource.validate.rng.SAXSchemaReader; 017 import org.xml.sax.InputSource; 018 import org.xml.sax.SAXException; 019 import org.xml.sax.XMLReader; 020 021 import java.io.IOException; 022 import java.net.URL; 023 024 /** 025 * Schema receiver implementation for NVDL schemas. 026 * 027 */ 028 class SchemaReceiverImpl implements SchemaReceiver { 029 /** 030 * Relax NG schema for nvdl schemas. 031 */ 032 private static final String NVDL_SCHEMA = "nvdl.rng"; 033 /** 034 * The type used for specifying RNC schemas. 035 */ 036 private static final String RNC_MEDIA_TYPE = "application/x-rnc"; 037 038 /** 039 * Properties. 040 */ 041 private final PropertyMap properties; 042 043 /** 044 * Flag indicating if we need to check only attributes, 045 * that means the root element is just a placeholder for the attributes. 046 */ 047 private final boolean attributesSchema; 048 049 /** 050 * The schema reader capable of parsing the input schema file. 051 * It will be an auto schema reader as NVDL is XML. 052 */ 053 private final SchemaReader autoSchemaReader; 054 055 /** 056 * Schema object created by this schema receiver. 057 */ 058 private Schema nvdlSchema = null; 059 060 /** 061 * Required properties. 062 */ 063 private static final PropertyId subSchemaProperties[] = { 064 ValidateProperty.ERROR_HANDLER, 065 ValidateProperty.XML_READER_CREATOR, 066 ValidateProperty.ENTITY_RESOLVER, 067 SchemaReceiverFactory.PROPERTY, 068 }; 069 070 /** 071 * Creates a schema receiver for NVDL schemas. 072 * 073 * @param properties Properties. 074 */ 075 public SchemaReceiverImpl(PropertyMap properties) { 076 this.attributesSchema = properties.contains(NvdlProperty.ATTRIBUTES_SCHEMA); 077 PropertyMapBuilder builder = new PropertyMapBuilder(); 078 for (int i = 0; i < subSchemaProperties.length; i++) { 079 Object value = properties.get(subSchemaProperties[i]); 080 if (value != null) 081 builder.put(subSchemaProperties[i], value); 082 } 083 this.properties = builder.toPropertyMap(); 084 this.autoSchemaReader = new AutoSchemaReader(SchemaReceiverFactory.PROPERTY.get(properties)); 085 } 086 087 /** 088 * 089 */ 090 public SchemaFuture installHandlers(XMLReader xr) { 091 PropertyMapBuilder builder = new PropertyMapBuilder(properties); 092 if (attributesSchema) 093 NvdlProperty.ATTRIBUTES_SCHEMA.add(builder); 094 return new SchemaImpl(builder.toPropertyMap()).installHandlers(xr, this); 095 } 096 097 Schema getNvdlSchema() throws IOException, IncorrectSchemaException, SAXException { 098 if (nvdlSchema == null) { 099 String className = SchemaReceiverImpl.class.getName(); 100 String resourceName = className.substring(0, className.lastIndexOf('.')).replace('.', '/') + "/resources/" + NVDL_SCHEMA; 101 URL nvdlSchemaUrl = getResource(resourceName); 102 nvdlSchema = SAXSchemaReader.getInstance().createSchema(new InputSource(nvdlSchemaUrl.toString()), 103 properties); 104 } 105 return nvdlSchema; 106 } 107 108 /** 109 * Get a resource using this class class loader. 110 * @param resourceName the resource. 111 * @return An URL pointing to the resource. 112 */ 113 private static URL getResource(String resourceName) { 114 ClassLoader cl = SchemaReceiverImpl.class.getClassLoader(); 115 // XXX see if we should borrow 1.2 code from Service 116 if (cl == null) 117 return ClassLoader.getSystemResource(resourceName); 118 else 119 return cl.getResource(resourceName); 120 } 121 122 /** 123 * Get the properties. 124 * @return a PropertyMap. 125 */ 126 PropertyMap getProperties() { 127 return properties; 128 } 129 130 /** 131 * Creates a child schema. This schema is referred in a validate action. 132 * 133 * @param inputSource The input source for the schema. 134 * @param schemaType The schema type. 135 * @param options Options specified for this schema in the NVDL script. 136 * @param isAttributesSchema Flag indicating if the schema should be modified 137 * to check attributes only. 138 * @return 139 * @throws IOException In case of IO problems. 140 * @throws IncorrectSchemaException In case of invalid schema. 141 * @throws SAXException In case if XML problems while creating the schema. 142 */ 143 Schema createChildSchema(InputSource inputSource, String schemaType, PropertyMap options, boolean isAttributesSchema) throws IOException, IncorrectSchemaException, SAXException { 144 SchemaReader reader = isRnc(schemaType) ? CompactSchemaReader.getInstance() : autoSchemaReader; 145 PropertyMapBuilder builder = new PropertyMapBuilder(properties); 146 if (isAttributesSchema) 147 NvdlProperty.ATTRIBUTES_SCHEMA.add(builder); 148 for (int i = 0, len = options.size(); i < len; i++) 149 builder.put(options.getKey(i), options.get(options.getKey(i))); 150 return reader.createSchema(inputSource, builder.toPropertyMap()); 151 } 152 153 /** 154 * Get an option for the given URI. 155 * @param uri The URI for an option. 156 * @return Either the option from the auto schema reader or 157 * from the compact schema reader. 158 */ 159 Option getOption(String uri) { 160 Option option = autoSchemaReader.getOption(uri); 161 if (option != null) 162 return option; 163 return CompactSchemaReader.getInstance().getOption(uri); 164 } 165 166 /** 167 * Checks is a schema type is RNC. 168 * @param schemaType The schema type specification. 169 * @return true if the schema type refers to a RNC schema. 170 */ 171 private static boolean isRnc(String schemaType) { 172 if (schemaType == null) 173 return false; 174 schemaType = schemaType.trim(); 175 return schemaType.equals(RNC_MEDIA_TYPE); 176 } 177 }