/**
* Copyright (c) 2011, SOCIETIES Consortium (WATERFORD INSTITUTE OF TECHNOLOGY (TSSG), HERIOT-WATT UNIVERSITY (HWU), SOLUTA.NET
* (SN), GERMAN AEROSPACE CENTRE (Deutsches Zentrum fuer Luft- und Raumfahrt e.V.) (DLR), Zavod za varnostne tehnologije
* informacijske družbe in elektronsko poslovanje (SETCCE), INSTITUTE OF COMMUNICATION AND COMPUTER SYSTEMS (ICCS), LAKE
* COMMUNICATIONS (LAKE), INTEL PERFORMANCE LEARNING SOLUTIONS LTD (INTEL), PORTUGAL TELECOM INOVAÇÃO, SA (PTIN), IBM Corp.,
* INSTITUT TELECOM (ITSUD), AMITEC DIACHYTI EFYIA PLIROFORIKI KAI EPIKINONIES ETERIA PERIORISMENIS EFTHINIS (AMITEC), TELECOM
* ITALIA S.p.a.(TI), TRIALOG (TRIALOG), Stiftelsen SINTEF (SINTEF), NEC EUROPE LTD (NEC))
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. 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.
*/
package org.societies.maven;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
/**
// * @extendsPlugin jaxb2
* @phase generate-sources
* @goal xsd
*/
public class XMPPMojo extends AbstractMojo
{
/**
* Output directory for schemas
*
* @parameter default-value="src/main/resources/"
*/
private String folderOutputDirectory;
/**
* Input directory for schemas
*
* @parameter default-value="${project.build.directory}/generated-resources/schemagen/"
*/
private String folderInputDirectory;
/**
* Input file name of the schema
*
* @parameter default-value="schema1.xsd"
*/
private String file;
/**
* httpNamespace of the schema
*
* @parameter
* @required
*/
private String httpNamespace;
/**
* packageName of the schema
*
* @parameter
* @required
*/
private String packageName;
/**
* Path to schema API of the schema
*
* @parameter default-value="../api/java/schema/"
*/
private String pathToParentSchema;
/**
* List of beans
* If this list is null, complexType
* finishing with Bean or BeanResult
* will be used
*
* @parameter
*/
private List beans;
public void execute() throws MojoExecutionException
{
// Init
initParameters();
// ---- Execute SchemaGen
// To do. For now, do mvn jaxb2:schemagen
// getLog().info("Don't forget to begin with a \"mvn jaxb2:schemagen\"");
// ---- Refactor the Schema
File schemaInputDirectory = new File(folderInputDirectory+file);
if (!schemaInputDirectory.canRead()) {
getLog().info("Schema XSD not readable. Refactoring aborted.");
return;
}
Scanner scanner = null;
try {
// Read the schema XSD content
scanner = new Scanner(schemaInputDirectory);
StringBuffer schemaContent = new StringBuffer();
while (scanner.hasNextLine()) {
schemaContent.append(scanner.nextLine()+"\n");
}
getLog().info("#################### Before refactoring");
getLog().info(schemaContent);
String newSchemaContent = new String();
// - Step 1: change "complexType" of Beans to "element"
Pattern patternComplexeType = null;
// Bean list not null : use it
if (null != beans) {
StringBuffer beansString = new StringBuffer();
int i = beans.size();
for(String bean : (List<String>) beans) {
i--;
if (i == 0) {
beansString.append(bean);
}
else {
beansString.append(bean+"|");
}
}
patternComplexeType = Pattern.compile("<xs:complexType name=\"("+beansString+")\"(.*?)</xs:complexType>", Pattern.DOTALL|Pattern.CASE_INSENSITIVE);
}
// Else use complexeType finishing by Bean or BeanResult
else {
patternComplexeType = Pattern.compile("<xs:complexType name=\"([^\"]*Bean(?:Result)?)\"(.*?)</xs:complexType>", Pattern.DOTALL|Pattern.CASE_INSENSITIVE);
}
Matcher matcherComplexeType = patternComplexeType.matcher(schemaContent);
newSchemaContent = matcherComplexeType.replaceAll("<xs:element name=\"$1\">\n\t<xs:complexType$2\t</xs:complexType>\n\t</xs:element>");
// getLog().info("#################### After ComplexeType");
// getLog().info(newSchemaContent);
// -- Step 2: Add relevant namespace to complex type
// Pattern patternTypeNamespace = Pattern.compile("type=\"(xs:(?!char|byte|short|int|long|float|double|boolean|string))\"", Pattern.CASE_INSENSITIVE);
Pattern patternTypeNamespace = Pattern.compile("(type|base)=\"((?!xs|ns[0-9]{1,3})[^\"]+)\"", Pattern.CASE_INSENSITIVE);
Matcher matcherTypeNamespace = patternTypeNamespace.matcher(newSchemaContent);
newSchemaContent = matcherTypeNamespace.replaceAll("$1=\"tns:$2\"");
// getLog().info("#################### After TypeNamespace");
// getLog().info(newSchemaContent);
// - Step 3: If they are not already added, add namespace in the root markup
Pattern patternNamespaceCheck = Pattern.compile("xmlns:tns", Pattern.CASE_INSENSITIVE);
Matcher matcherNamespaceCheck = patternNamespaceCheck.matcher(newSchemaContent);
if (!matcherNamespaceCheck.find()) {
Pattern patternNamespace = Pattern.compile("<xs:schema version=\"1.0\" (.*)xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">", Pattern.DOTALL|Pattern.CASE_INSENSITIVE);
Matcher matcherNamespace = patternNamespace.matcher(newSchemaContent);
newSchemaContent = matcherNamespace.replaceAll("<xs:schema version=\"1.0\" elementFormDefault=\"qualified\"\n\ttargetNamespace=\""+httpNamespace+"\"\n\txmlns:tns=\""+httpNamespace+"\"\n\t$1\n\txmlns:xs=\"http://www.w3.org/2001/XMLSchema\">");
// getLog().info("#################### After Namespace");
// getLog().info(newSchemaContent);
}
// - Step 4: If this schema import other existing schema, add their relevant URL
Pattern patternImportCheck = Pattern.compile("schemaLocation", Pattern.CASE_INSENSITIVE);
Matcher matcherImportCheck = patternImportCheck.matcher(newSchemaContent);
if (matcherImportCheck.find()) {
Pattern patternIsInternal = Pattern.compile("internal/", Pattern.CASE_INSENSITIVE);
Matcher matcherIsInternal = patternIsInternal.matcher(httpNamespace);
boolean isInternal = matcherIsInternal.find();
Pattern patternImport = Pattern.compile("<xs:import namespace=\"(http://societies.org/api/(internal/)?schema/([^\"]+))\" schemaLocation=\"([^\"]*)\" ?/>", Pattern.CASE_INSENSITIVE);
Matcher matcherImport = patternImport.matcher(newSchemaContent);
StringBuffer importsContent = new StringBuffer();
while (matcherImport.find()) {
Pattern patternInternalCheck = Pattern.compile("internal/", Pattern.CASE_INSENSITIVE);
Matcher matcherInternalCheck = patternInternalCheck.matcher(matcherImport.group());
String httpNs = matcherImport.group(1);
String typeHttpNs = matcherImport.group(2);
String endHttpNs = matcherImport.group(3);
if (matcherInternalCheck.find()) {
// getLog().info("internal:"+httpNs);
// getLog().info("internal:"+typeHttpNs);
// getLog().info("internal:"+endHttpNs);
matcherImport.appendReplacement(importsContent, "<xs:import namespace=\"http://societies.org/api/$2schema/$3\" schemaLocation=\"org.societies.api."+typeHttpNs.replace("/", ".")+"schema."+endHttpNs.replace("/", ".")+".xsd\" />");
}
else {
// getLog().info("external:"+httpNs);
// getLog().info("external:"+typeHttpNs);
// getLog().info("external:"+endHttpNs);
matcherImport.appendReplacement(importsContent, "<xs:import namespace=\"http://societies.org/api/$2schema/$3\" schemaLocation=\""+(isInternal ? "../../../../external/src/main/resources/" : "")+"org.societies.api.schema."+endHttpNs.replace("/", ".")+".xsd\" />");
}
}
matcherImport.appendTail(importsContent);
newSchemaContent = importsContent.toString();
getLog().info("#################### After Import");
getLog().info(newSchemaContent);
}
getLog().info("#################### After refactoring");
getLog().info(newSchemaContent);
// - Step 5: Save in the folderOutputDirectory
FileWriter newFile = new FileWriter(folderOutputDirectory+packageName+".xsd");
newFile.write(newSchemaContent);
newFile.close();
// - Step 6: Save in the Societies Schema API
// FileWriter finalSchema = new FileWriter(pathToParentSchema+folderOutputDirectory+packageName+".xsd");
// finalSchema.write(newSchemaContent);
// finalSchema.close();
} catch (FileNotFoundException e) {
getLog().error("File not found");
getLog().error(e);
} catch (IOException e) {
getLog().error("Error in file usage");
getLog().error(e);
}
finally {
scanner.close();
}
}
/**
* Init parameters
*/
private void initParameters() {
if (!folderOutputDirectory.equals(".") && !folderOutputDirectory.endsWith("/")) {
folderOutputDirectory += "/";
}
if (!folderInputDirectory.equals(".") && !folderInputDirectory.endsWith("/")) {
folderInputDirectory += "/";
}
if (!pathToParentSchema.equals(".") && !pathToParentSchema.endsWith("/")) {
pathToParentSchema += "/";
}
}
private String httpNs2packageNs(String httpNs) {
// getLog().info("httpNs2packageNs: "+httpNs);
// Pattern pattern = Pattern.compile("http://societies.org/api/(internal/)?schema/([^\"]+)", Pattern.CASE_INSENSITIVE);
// Matcher matcher = pattern.matcher(httpNs);
// String type = matcher.group(1);
// String endHttpNs = matcher.group(2);
// getLog().info("httpNs2packageNs: "+type+", endHttpNs:"+endHttpNs);
// return new String("org.societies.api.schema."+type.replace("/", ".")+endHttpNs.replace("/", "."));
return new String("org.societies.api.schema.");
}
}