Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Thomas Børlum
committed
Nov 22, 2011
1 parent
201acbc
commit b163591
Showing
7 changed files
with
332 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
234 changes: 234 additions & 0 deletions
234
nsp/batch-copy-ws/src/main/java/dk/nsi/stamdata/replication/tools/SchemaGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
/** | ||
* The contents of this file are subject to the Mozilla Public | ||
* License Version 1.1 (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.mozilla.org/MPL/ | ||
* | ||
* Software distributed under the License is distributed on an "AS | ||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | ||
* implied. See the License for the specific language governing | ||
* rights and limitations under the License. | ||
* | ||
* Contributor(s): Contributors are attributed in the source code | ||
* where applicable. | ||
* | ||
* The Original Code is "Stamdata". | ||
* | ||
* The Initial Developer of the Original Code is Trifork Public A/S. | ||
* | ||
* Portions created for the Original Code are Copyright 2011, | ||
* Lægemiddelstyrelsen. All Rights Reserved. | ||
* | ||
* Portions created for the FMKi Project are Copyright 2011, | ||
* National Board of e-Health (NSI). All Rights Reserved. | ||
*/ | ||
package dk.nsi.stamdata.replication.tools; | ||
|
||
import com.google.inject.Guice; | ||
import com.google.inject.Key; | ||
import com.google.inject.TypeLiteral; | ||
import com.trifork.stamdata.Namespace; | ||
import com.trifork.stamdata.Nullable; | ||
import com.trifork.stamdata.persistence.RecordSpecification; | ||
import com.trifork.stamdata.specs.SikredeRecordSpecs; | ||
import com.trifork.stamdata.specs.YderregisterRecordSpecs; | ||
import dk.nsi.stamdata.views.View; | ||
import dk.nsi.stamdata.views.ViewModule; | ||
import org.dom4j.Document; | ||
import org.dom4j.DocumentFactory; | ||
import org.dom4j.Element; | ||
import org.dom4j.io.OutputFormat; | ||
import org.dom4j.io.XMLWriter; | ||
|
||
import javax.xml.bind.annotation.XmlSchema; | ||
import javax.xml.bind.annotation.XmlTransient; | ||
import java.io.File; | ||
import java.io.FileWriter; | ||
import java.io.IOException; | ||
import java.io.Writer; | ||
import java.lang.reflect.Field; | ||
import java.math.BigInteger; | ||
import java.util.Collection; | ||
import java.util.Date; | ||
import java.util.Map; | ||
|
||
import static com.trifork.stamdata.Preconditions.checkArgument; | ||
|
||
public class SchemaGenerator | ||
{ | ||
private static final Key<Map<String, Class<? extends View>>> view = Key.get(new TypeLiteral<Map<String, Class<? extends View>>>() {}); | ||
|
||
public static void main(String[] args) throws IOException | ||
{ | ||
File outputDir = new File(args[0]); | ||
|
||
Collection<Class<? extends View>> views = Guice.createInjector(new ViewModule()).getInstance(view).values(); | ||
|
||
for (Class<? extends View> view : views) | ||
{ | ||
String packageName = view.getPackage().getName(); | ||
String subDirName = packageName.substring(packageName.lastIndexOf(".") + 1); | ||
String viewName = view.getSimpleName().toLowerCase(); | ||
|
||
Writer writer = createWriterFor(outputDir, subDirName, viewName); | ||
|
||
generate(view, writer); | ||
|
||
writer.flush(); | ||
writer.close(); | ||
} | ||
|
||
// HACK: Make generic for all record specs. | ||
|
||
generateRecordXsd(outputDir, "sikrede", "sikrede", SikredeRecordSpecs.ENTRY_RECORD_SPEC); | ||
generateRecordXsd(outputDir, "yderregisteret", "yder", YderregisterRecordSpecs.YDER_RECORD_TYPE); | ||
generateRecordXsd(outputDir, "yderregisteret", "person", YderregisterRecordSpecs.PERSON_RECORD_TYPE); | ||
} | ||
|
||
private static void generateRecordXsd(File outputDir, String register, String entityName, RecordSpecification spec) throws IOException | ||
{ | ||
Writer writer = createWriterFor(outputDir, register, entityName); | ||
|
||
generate(spec, writer, register); | ||
|
||
writer.flush(); | ||
writer.close(); | ||
} | ||
|
||
private static FileWriter createWriterFor(File outputDir, String register, String entityName) throws IOException | ||
{ | ||
File registerDir = new File(outputDir, register); | ||
registerDir.mkdirs(); | ||
|
||
File schemaFile = new File(registerDir, entityName + ".xsd"); | ||
return new FileWriter(schemaFile); | ||
} | ||
|
||
public static void generate(Class<? extends View> entity, Writer writer) throws IOException | ||
{ | ||
Document doc = DocumentFactory.getInstance().createDocument(); | ||
|
||
String targetNamespace = entity.getPackage().getAnnotation(XmlSchema.class).namespace(); | ||
String entityName = entity.getSimpleName().toLowerCase(); | ||
|
||
Element all = generate(doc, targetNamespace, entityName); | ||
|
||
for (Field method : entity.getDeclaredFields()) | ||
{ | ||
if (method.isAnnotationPresent(XmlTransient.class)) continue; | ||
|
||
String name = method.getName(); | ||
String type = convert2SchemaType(method); | ||
addElement(all, name, type, null); | ||
} | ||
|
||
XMLWriter xmlWriter = new XMLWriter(writer, OutputFormat.createPrettyPrint()); | ||
xmlWriter.write(doc); | ||
} | ||
|
||
private static Element generate(Document doc, String namespace, String entityName) | ||
{ | ||
Element root = doc.addElement("xs:schema"); | ||
|
||
root.addNamespace("xs", "http://www.w3.org/2001/XMLSchema"); | ||
root.addNamespace("tns", namespace); | ||
root.addAttribute("targetNamespace", namespace); | ||
|
||
Element element = root.addElement("xs:element"); | ||
element.addAttribute("name", entityName); | ||
|
||
Element complexType = element.addElement("xs:complexType"); | ||
|
||
// We use "all" and not "sequence" we cause we cannot tell from the | ||
// class the order of the elements. | ||
// | ||
return complexType.addElement("xs:all"); | ||
} | ||
|
||
private static void addElement(Element parent, String name, String type, @Nullable Integer length) | ||
{ | ||
Element field = parent.addElement("xs:element"); | ||
field.addAttribute("name", name); | ||
|
||
if (length != null && type.equals("xs:string")) | ||
{ | ||
field.addElement("xs:simpleType").addElement("xs:restriction").addElement("xs:maxLength").addAttribute("value", length.toString()); | ||
} | ||
else | ||
{ | ||
field.addAttribute("type", type); | ||
} | ||
} | ||
|
||
private static String convert2SchemaType(Field field) | ||
{ | ||
if (String.class.isAssignableFrom(field.getType())) | ||
{ | ||
return "xs:string"; | ||
} | ||
else if (Long.class.isAssignableFrom(field.getType()) || BigInteger.class.isAssignableFrom(field.getType()) || long.class.isAssignableFrom(field.getType()) || int.class.isAssignableFrom(field.getType())) | ||
{ | ||
return "xs:integer"; | ||
} | ||
else if (Date.class.isAssignableFrom(field.getType())) | ||
{ | ||
return "xs:dateTime"; | ||
} | ||
else if (Float.class.isAssignableFrom(field.getType())) | ||
{ | ||
return "xs:float"; | ||
} | ||
else if (Double.class.isAssignableFrom(field.getType())) | ||
{ | ||
return "xs:double"; | ||
} | ||
else if (Boolean.class.isAssignableFrom(field.getType()) || boolean.class.isAssignableFrom(field.getType())) | ||
{ | ||
return "xs:boolean"; | ||
} | ||
else | ||
{ | ||
checkArgument(false, "Return type '%s' on field %s is not supported.", field.getType(), field.toString()); | ||
return null; | ||
} | ||
} | ||
|
||
public static void generate(RecordSpecification specification, Writer writer, String register) throws IOException | ||
{ | ||
Document doc = DocumentFactory.getInstance().createDocument(); | ||
|
||
// FIXME: Register added to record spec. | ||
|
||
String namespace = Namespace.STAMDATA_3_0 + "/" + register; | ||
String entityName = specification.getTable().toLowerCase(); | ||
|
||
Element all = generate(doc, namespace, entityName); | ||
|
||
for (RecordSpecification.FieldSpecification field : specification.getFieldSpecs()) | ||
{ | ||
addElement(all, field.name, convert2XsdType(field.type), field.length); | ||
} | ||
|
||
all.addElement("xs:element").addAttribute("name", "validFrom").addAttribute("type", "xs:dateTime"); | ||
all.addElement("xs:element").addAttribute("name", "validTo").addAttribute("type", "xs:dateTime"); | ||
|
||
XMLWriter xmlWriter = new XMLWriter(writer, OutputFormat.createPrettyPrint()); | ||
xmlWriter.write(doc); | ||
} | ||
|
||
private static String convert2XsdType(RecordSpecification.RecordFieldType fieldType) | ||
{ | ||
if (fieldType == RecordSpecification.RecordFieldType.ALPHANUMERICAL) | ||
{ | ||
return "xs:string"; | ||
} | ||
else if (fieldType == RecordSpecification.RecordFieldType.NUMERICAL) | ||
{ | ||
return "xs:integer"; | ||
} | ||
else | ||
{ | ||
throw new AssertionError(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.