Added LanguageModuleLoader unit tests.

This commit is contained in:
Willem Cazander 2014-03-07 16:58:33 +01:00
parent a3863c1637
commit 651b2a99e4
6 changed files with 301 additions and 62 deletions

View file

@ -51,14 +51,12 @@ import org.xml.sax.helpers.XMLReaderFactory;
public class DefaultX4OLanguageLoader implements X4OLanguageLoader { public class DefaultX4OLanguageLoader implements X4OLanguageLoader {
private Logger logger = null; private Logger logger = null;
protected List<VersionedResources> modulesAll = null;
/** /**
* Creates the DefaultX4OLanguageLoader. * Creates the DefaultX4OLanguageLoader.
*/ */
public DefaultX4OLanguageLoader() { public DefaultX4OLanguageLoader() {
logger = Logger.getLogger(DefaultX4OLanguageLoader.class.getName()); logger = Logger.getLogger(DefaultX4OLanguageLoader.class.getName());
modulesAll = new ArrayList<VersionedResources>(20);
} }
/** /**
@ -84,31 +82,12 @@ TODO: if (language.getLanguageConfiguration().hasX4ODebugWriter()) {
*/ */
public void loadLanguage(X4OLanguageLocal languageLocal, String language,String languageVersion) throws X4OLanguageLoaderException { public void loadLanguage(X4OLanguageLocal languageLocal, String language,String languageVersion) throws X4OLanguageLoaderException {
logger.finer("Loading all modules for language: "+language); logger.finer("Loading all modules for language: "+language);
try { List<VersionedResources> modulesAll = loadLanguageModules(languageLocal,language);
loadLanguageModules(languageLocal,language); modulesAll = filterVersionModules(modulesAll,languageLocal,languageVersion);
} catch (IOException e) { validateModules(modulesAll);
throw new X4OLanguageLoaderException(e);
} catch (SAXException e) {
throw new X4OLanguageLoaderException(e);
}
X4OLanguageVersionFilter lvf;
try {
lvf = (X4OLanguageVersionFilter)X4OLanguageClassLoader.newInstance(languageLocal.getLanguageConfiguration().getDefaultLanguageVersionFilter());
} catch (InstantiationException e) {
throw new X4OLanguageLoaderException(e);
} catch (IllegalAccessException e) {
throw new X4OLanguageLoaderException(e);
}
int loaded = 0; int loaded = 0;
for (VersionedResources versionedResources:modulesAll) { for (VersionedResources versionedResources:modulesAll) {
List<String> versions = new ArrayList<String>();
versions.add(versionedResources.version); // FIXME
String modulesVersion = lvf.filterVersion(languageVersion, versions);
if (modulesVersion==null) {
continue;
}
X4OLanguageModuleLoader loader; X4OLanguageModuleLoader loader;
for (String value:versionedResources.eldResources) { for (String value:versionedResources.eldResources) {
String languagePrefix = languageLocal.getLanguageConfiguration().getLanguageResourcePathPrefix(); String languagePrefix = languageLocal.getLanguageConfiguration().getLanguageResourcePathPrefix();
@ -151,7 +130,51 @@ TODO: if (language.getLanguageConfiguration().hasX4ODebugWriter()) {
throw new X4OLanguageLoaderException("No modules defined for version: "+languageVersion); throw new X4OLanguageLoaderException("No modules defined for version: "+languageVersion);
} }
} }
private List<VersionedResources> filterVersionModules(List<VersionedResources> resources,X4OLanguageLocal languageLocal,String languageVersion) throws X4OLanguageLoaderException {
List<VersionedResources> result = new ArrayList<VersionedResources>(resources.size());
X4OLanguageVersionFilter lvf;
try {
lvf = (X4OLanguageVersionFilter)X4OLanguageClassLoader.newInstance(languageLocal.getLanguageConfiguration().getDefaultLanguageVersionFilter());
} catch (InstantiationException e) {
throw new X4OLanguageLoaderException(e);
} catch (IllegalAccessException e) {
throw new X4OLanguageLoaderException(e);
}
for (VersionedResources versionedResources:resources) {
List<String> versions = new ArrayList<String>();
versions.add(versionedResources.version); // FIXME
String modulesVersion = lvf.filterVersion(languageVersion, versions);
if (modulesVersion==null) {
continue;
}
result.add(versionedResources);
}
return result;
}
protected void validateModules(List<VersionedResources> resources) throws X4OLanguageLoaderException {
List<String> eldResources = new ArrayList<String>(5);
List<String> moduleLoaders = new ArrayList<String>(5);
List<String> elbResources = new ArrayList<String>(5);
List<String> siblingLoaders = new ArrayList<String>(5);
for (VersionedResources vr:resources) {
validateModuleList(eldResources,vr.eldResources,"eld-resource");
validateModuleList(moduleLoaders,vr.moduleLoaders,"module-loader");
validateModuleList(elbResources,vr.elbResources,"elb-resource");
validateModuleList(siblingLoaders,vr.siblingLoaders,"sibling-loader");
}
}
private void validateModuleList(List<String> data,List<String> values,String xmlTag) throws X4OLanguageLoaderException {
for (String value:values) {
if (data.contains(value)) {
throw new X4OLanguageLoaderException("Duplicate "+xmlTag+" entry detected; "+value);
}
data.add(value);
}
}
private void loadModule(X4OLanguageLocal languageLocal,X4OLanguageModuleLoader loader,String resource,VersionedResources versionedResources) throws X4OLanguageLoaderException { private void loadModule(X4OLanguageLocal languageLocal,X4OLanguageModuleLoader loader,String resource,VersionedResources versionedResources) throws X4OLanguageLoaderException {
X4OLanguageModuleLocal module; X4OLanguageModuleLocal module;
try { try {
@ -187,7 +210,8 @@ TODO: if (language.getLanguageConfiguration().hasX4ODebugWriter()) {
* @param languageLocal The ElementLanguage to load for. * @param languageLocal The ElementLanguage to load for.
* @param language The language to load. * @param language The language to load.
*/ */
protected void loadLanguageModules(X4OLanguageLocal languageLocal,String language) throws IOException, SAXException { protected List<VersionedResources> loadLanguageModules(X4OLanguageLocal languageLocal,String language) throws X4OLanguageLoaderException {
List<VersionedResources> result = new ArrayList<VersionedResources>(15);
StringBuilder buf = new StringBuilder(150); StringBuilder buf = new StringBuilder(150);
buf.append(languageLocal.getLanguageConfiguration().getLanguageResourcePathPrefix()); buf.append(languageLocal.getLanguageConfiguration().getLanguageResourcePathPrefix());
buf.append('/'); buf.append('/');
@ -197,18 +221,25 @@ TODO: if (language.getLanguageConfiguration().hasX4ODebugWriter()) {
buf.append(languageLocal.getLanguageConfiguration().getLanguageResourceModulesFileName()); buf.append(languageLocal.getLanguageConfiguration().getLanguageResourceModulesFileName());
logger.finer("loading X4O language: "+language); logger.finer("loading X4O language: "+language);
Enumeration<URL> e = Thread.currentThread().getContextClassLoader().getResources(buf.toString()); try {
while(e.hasMoreElements()) { Enumeration<URL> e = Thread.currentThread().getContextClassLoader().getResources(buf.toString());
URL u = e.nextElement(); while(e.hasMoreElements()) {
logMessage(languageLocal,"Loading relative modules: "+u+" for: "+language); URL u = e.nextElement();
loadModulesXml(u.openStream(),u.toString()); logMessage(languageLocal,"Loading relative modules: "+u+" for: "+language);
} result.addAll(loadLanguageModulesXml(u.openStream(),u.toString()));
}
e = Thread.currentThread().getContextClassLoader().getResources("/"+buf.toString());
while(e.hasMoreElements()) { e = Thread.currentThread().getContextClassLoader().getResources("/"+buf.toString());
URL u = e.nextElement(); while(e.hasMoreElements()) {
logMessage(languageLocal,"Loading root modules: "+u+" for: "+language); URL u = e.nextElement();
loadModulesXml(u.openStream(),u.toString()); logMessage(languageLocal,"Loading root modules: "+u+" for: "+language);
result.addAll(loadLanguageModulesXml(u.openStream(),u.toString()));
}
return result;
} catch (IOException e) {
throw new X4OLanguageLoaderException(e);
} catch (SAXException e) {
throw new X4OLanguageLoaderException(e);
} }
} }
@ -218,7 +249,7 @@ TODO: if (language.getLanguageConfiguration().hasX4ODebugWriter()) {
* @throws IOException * @throws IOException
* @throws SAXException * @throws SAXException
*/ */
protected void loadModulesXml(InputStream in,String loadedFrom) throws IOException, SAXException { protected List<VersionedResources> loadLanguageModulesXml(InputStream in,String loadedFrom) throws IOException, SAXException {
if (in==null) { if (in==null) {
throw new NullPointerException("Can't parse null input stream"); throw new NullPointerException("Can't parse null input stream");
} }
@ -229,24 +260,32 @@ TODO: if (language.getLanguageConfiguration().hasX4ODebugWriter()) {
saxParser.setProperty("http://xml.org/sax/properties/declaration-handler",xth); saxParser.setProperty("http://xml.org/sax/properties/declaration-handler",xth);
try { try {
saxParser.parse(new InputSource(in)); saxParser.parse(new InputSource(in));
return xth.getResult();
} finally { } finally {
in.close(); in.close();
} }
} }
private class ModulesTagHandler extends DefaultHandler2 { private class ModulesTagHandler extends DefaultHandler2 {
private StringBuffer buf = new StringBuffer(); private StringBuffer buf = new StringBuffer();
private String loadedFrom = null; private String loadedFrom = null;
private VersionedResources versionedResources = null; private VersionedResources versionedResources = null;
private List<VersionedResources> result = null;
public ModulesTagHandler(String loadedFrom) { public ModulesTagHandler(String loadedFrom) {
this.loadedFrom=loadedFrom; this.loadedFrom=loadedFrom;
this.result = new ArrayList<VersionedResources>(5);
} }
public List<VersionedResources> getResult()
{
return result;
}
@Override @Override
public void startDocument() throws SAXException { public void startDocument() throws SAXException {
} }
@Override @Override
public void startElement(String namespaceUri, String tag, String qName,Attributes attr) throws SAXException { public void startElement(String namespaceUri, String tag, String qName,Attributes attr) throws SAXException {
if ("language".equals(tag)) { if ("language".equals(tag)) {
@ -257,7 +296,7 @@ TODO: if (language.getLanguageConfiguration().hasX4ODebugWriter()) {
logger.finest("Version attribute: "+version); logger.finest("Version attribute: "+version);
} }
} }
@Override @Override
public void endElement(String namespaceUri, String tag,String qName) throws SAXException { public void endElement(String namespaceUri, String tag,String qName) throws SAXException {
@ -270,7 +309,7 @@ TODO: if (language.getLanguageConfiguration().hasX4ODebugWriter()) {
return; return;
} }
if ("language".equals(tag)) { if ("language".equals(tag)) {
modulesAll.add(versionedResources); result.add(versionedResources);
versionedResources = null; versionedResources = null;
return; return;
} }
@ -300,7 +339,7 @@ TODO: if (language.getLanguageConfiguration().hasX4ODebugWriter()) {
} }
} }
private class VersionedResources { protected class VersionedResources {
public String version; public String version;
public String loadedFrom; public String loadedFrom;
public List<String> eldResources = new ArrayList<String>(5); public List<String> eldResources = new ArrayList<String>(5);

View file

@ -22,10 +22,13 @@
*/ */
package org.x4o.xml.lang; package org.x4o.xml.lang;
import java.io.InputStream;
import java.util.List;
import org.x4o.xml.X4ODriver; import org.x4o.xml.X4ODriver;
import org.x4o.xml.lang.X4OLanguage; import org.x4o.xml.lang.X4OLanguage;
import org.x4o.xml.lang.X4OLanguageLoader;
import org.x4o.xml.lang.X4OLanguageLocal; import org.x4o.xml.lang.X4OLanguageLocal;
import org.x4o.xml.lang.DefaultX4OLanguageLoader.VersionedResources;
import org.x4o.xml.lang.phase.DefaultX4OPhaseManager; import org.x4o.xml.lang.phase.DefaultX4OPhaseManager;
import org.x4o.xml.lang.phase.X4OPhaseLanguageInit; import org.x4o.xml.lang.phase.X4OPhaseLanguageInit;
import org.x4o.xml.lang.phase.X4OPhaseLanguageRead; import org.x4o.xml.lang.phase.X4OPhaseLanguageRead;
@ -80,27 +83,69 @@ public class DefaultX4OLanguageLoaderTest extends TestCase {
loader.loadLanguage((X4OLanguageLocal)result, "test", "1.0"); loader.loadLanguage((X4OLanguageLocal)result, "test", "1.0");
} }
public void testLanguag() throws Exception { public void testModulesSimple() throws Exception {
// loader.loadModulesXml(in); InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("tests/modules/test-modules-simple.xml");
assertNotNull(in);
List<VersionedResources> result = loader.loadLanguageModulesXml(in, "test-modules-simple.xml");
assertNotNull(result);
assertFalse(result.isEmpty());
assertTrue("Simple test returned non-one result: "+result.size(),result.size()==1);
} }
/* public void testModulesFull() throws Exception {
public void testLanguageURINameSpaceTest() throws Exception { InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("tests/modules/test-modules-full.xml");
Map<String,String> languageMap = loader.loadLanguageModules(parser.getElementLanguage(), "test"); assertNotNull(in);
assertTrue("No uri for test.eld", languageMap.containsKey("eld.http://test.x4o.org/eld/test.eld")); List<VersionedResources> result = loader.loadLanguageModulesXml(in, "test-modules-full.xml");
assertEquals("test.eld", languageMap.get("eld.http://test.x4o.org/eld/test.eld")); assertNotNull(result);
assertFalse(result.isEmpty());
VersionedResources vr = result.get(0);
assertTrue(vr.eldResources.size()>1);
assertTrue(vr.moduleLoaders.size()>1);
assertTrue(vr.elbResources.size()>1);
assertTrue(vr.siblingLoaders.size()==1);
} }
public void testLanguageURINameSpaceX4O() throws Exception { public void testModulesDuplicateLoaderNoError() throws Exception {
Map<String,String> languageMap = loader.loadLanguageModules(parser.getElementLanguage(), "x4o"); InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("tests/modules/test-modules-err-loader.xml");
assertTrue("No uri for x4o-lang.eld", languageMap.containsKey("eld.http://eld.x4o.org/eld/x4o-lang.eld")); assertNotNull(in);
assertEquals("x4o-lang.eld", languageMap.get("eld.http://eld.x4o.org/eld/x4o-lang.eld")); List<VersionedResources> result = loader.loadLanguageModulesXml(in, "test-modules-err-loader.xml");
assertNotNull(result);
assertFalse(result.isEmpty());
} }
public void testLanguageURINameSpaceELD() throws Exception { public void testModulesDuplicateLoader() throws Exception {
Map<String,String> languageMap = loader.loadLanguageModules(parser.getElementLanguage(), "eld"); InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("tests/modules/test-modules-err-loader.xml");
assertTrue("No uri for eld-lang.eld", languageMap.containsKey("eld.http://eld.x4o.org/eld/eld-lang.eld")); assertNotNull(in);
assertEquals("eld-lang.eld", languageMap.get("eld.http://eld.x4o.org/eld/eld-lang.eld")); List<VersionedResources> result = loader.loadLanguageModulesXml(in, "test-modules-err-loader.xml");
assertNotNull(result);
assertFalse(result.isEmpty());
Exception e=null;
try {
loader.validateModules(result);
} catch (Exception ee) {
e=ee;
}
assertNotNull(e);
assertTrue("No 'Duplicate' found in message: "+e.getMessage(),e.getMessage().contains("Duplicate"));
assertTrue("No 'module-loader' found in message: "+e.getMessage(),e.getMessage().contains("module-loader"));
}
public void testModulesDuplicateSiblingLoader() throws Exception {
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("tests/modules/test-modules-err-sibling.xml");
assertNotNull(in);
List<VersionedResources> result = loader.loadLanguageModulesXml(in, "test-modules-err-sibling.xml");
assertNotNull(result);
assertFalse(result.isEmpty());
Exception e=null;
try {
loader.validateModules(result);
} catch (Exception ee) {
e=ee;
}
assertNotNull(e);
assertTrue("No 'Duplicate' found in message: "+e.getMessage(),e.getMessage().contains("Duplicate"));
assertTrue("No 'sibling-loader' found in message: "+e.getMessage(),e.getMessage().contains("sibling-loader"));
} }
*/
} }

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2004-2013, Willem Cazander
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<modules version="1.0"
xmlns="http://language.x4o.org/xml/ns/modules"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://language.x4o.org/xml/ns/modules http://language.x4o.org/xml/ns/modules-1.0.xsd"
>
<language version="1.0">
<module-loader>org.foo.bar.test.loader.EqualLoader</module-loader>
<module-loader>org.foo.bar.test.loader.EqualLoader</module-loader>
</language>
</modules>

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2004-2013, Willem Cazander
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<modules version="1.0"
xmlns="http://language.x4o.org/xml/ns/modules"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://language.x4o.org/xml/ns/modules http://language.x4o.org/xml/ns/modules-1.0.xsd"
>
<language version="1.0">
<sibling-loader>org.foo.bar.test.loader.EqualSiblingLoader</sibling-loader>
<sibling-loader>org.foo.bar.test.loader.EqualSiblingLoader</sibling-loader>
</language>
</modules>

View file

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2004-2013, Willem Cazander
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<modules version="1.0"
xmlns="http://language.x4o.org/xml/ns/modules"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://language.x4o.org/xml/ns/modules http://language.x4o.org/xml/ns/modules-1.0.xsd"
>
<language version="1.0">
<eld-resource>my-lib0.eld</eld-resource>
<eld-resource>my-lib1.eld</eld-resource>
<eld-resource>my-lib2.eld</eld-resource>
<eld-resource>my-lib3.eld</eld-resource>
<eld-resource>my-lib4.eld</eld-resource>
<eld-resource>my-lib5.eld</eld-resource>
<eld-resource>my-lib6.eld</eld-resource>
<eld-resource>my-lib7.eld</eld-resource>
<elb-resource>my-bean0.elb</elb-resource>
<elb-resource>my-bean1.elb</elb-resource>
<elb-resource>my-bean2.elb</elb-resource>
<module-loader>org.foo.bar.test.loader.FirstLoader</module-loader>
<module-loader>org.foo.bar.test.loader.SecondLoader</module-loader>
<module-loader>org.foo.bar.test.loader.LastLoader</module-loader>
<sibling-loader>org.foo.bar.test.loader.OtherLanguageSiblingLoader</sibling-loader>
</language>
</modules>

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2004-2013, Willem Cazander
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<modules version="1.0"
xmlns="http://language.x4o.org/xml/ns/modules"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://language.x4o.org/xml/ns/modules http://language.x4o.org/xml/ns/modules-1.0.xsd"
>
<language version="1.0">
<eld-resource>my-language.eld</eld-resource>
</language>
</modules>