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 }