package gr.ntua.ivml.mint.actions;
import gr.ntua.ivml.mint.db.DB;
import gr.ntua.ivml.mint.persistent.DataUpload;
import gr.ntua.ivml.mint.persistent.Mapping;
import gr.ntua.ivml.mint.persistent.Organization;
import gr.ntua.ivml.mint.persistent.Transformation;
import gr.ntua.ivml.mint.persistent.XMLNode;
import gr.ntua.ivml.mint.persistent.XmlObject;
import gr.ntua.ivml.mint.persistent.XmlSchema;
import gr.ntua.ivml.mint.persistent.XpathHolder;
import gr.ntua.ivml.mint.util.Config;
import gr.ntua.ivml.mint.xml.transform.ChainTransform;
import gr.ntua.ivml.mint.xml.transform.XMLFormatter;
import gr.ntua.ivml.mint.xml.transform.XSLTGenerator;
import gr.ntua.ivml.mint.xml.transform.XSLTransform;
import gr.ntua.ivml.mint.xsd.ReportErrorHandler;
import gr.ntua.ivml.mint.xsd.SchemaValidator;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.servlet.ServletContext;
import javax.xml.transform.stream.StreamSource;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.apache.struts2.util.ServletContextAware;
import org.xml.sax.SAXParseException;
@Results({
@Result(name="input", location="xmlPreviewPanel.jsp"),
@Result(name="error", location="xmlPreviewPanel.jsp"),
@Result(name="success", location="xmlPreviewPanel.jsp" ),
@Result(name="previewInput", location="xmlPreviewPanel.jsp" )
})
public class XMLPreview extends GeneralAction implements ServletContextAware {
public static final String SCENE_INPUT = "input";
public static final String SCENE_SELECT_MAPPING = "selectableMap";
public static final String SCENE_FIXED_MAPPING = "fixedMap";
public static final String SCENE_PUBLISHED_ERROR = "publishedError";
public static class PreviewTab {
public static final int LONG_LENGTH_CONTENT = 10000;
public static final String TYPE_TEXT = "text";
public static final String TYPE_HTML = "html";
public static final String TYPE_XML = "xml";
public static final String TYPE_RDF = "rdf";
public static final String TYPE_JSP = "jsp";
String type;
String url;
String content;
String title;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public boolean hasLongContent() {
return content.length() > LONG_LENGTH_CONTENT;
}
public PreviewTab( String title, String content, String type ) {
this.content = content;
this.title = title;
this.type = type;
}
public PreviewTab( String title, String content, String type, String url ) {
this.content = content;
this.title = title;
this.type = type;
this.url = url;
}
public PreviewTab( Exception e ) {
title = "Exception";
type = TYPE_TEXT;
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter( sw ));
content = sw.toString();
}
public String toString() {
String result = "";
if(title != null) result += title;
else result += "PREVIEW-TAB";
if(type != null) result += "(" + type + ")";
result += ":";
result += content;
return result;
}
}
protected final Logger log = Logger.getLogger(getClass());
private long selMapping=0;
private String uploadId;
private String nodeId;
private Mapping mapping;
private String error;
private ServletContext sc;
private boolean truncated=false;
private List<PreviewTab> tabs;
private ArrayList<SAXParseException> report;
private String scene;
private boolean mappingSelector=false;
private String validation="";
private boolean isValid=false;
private List<Mapping> maplist= new ArrayList<Mapping>();
public List<Mapping> getMaplist() {
try{
List<Mapping> alllist= DB.getMappingDAO().findAllOrderOrg();
for(int i=0;i<alllist.size();i++){
//now add the shared ones if not already in list
Mapping em=alllist.get(i);
//if shared and not locked add to template list
if(em.isShared() && !em.isLocked(getUser(), getSessionId())){
maplist.add(em);
}
else if(!em.isShared() && !em.isLocked(getUser(), getSessionId())){
//if not shared but belongs to accessible org
Organization org=em.getOrganization();
//need to check accessible and their parents
List<Organization> deporgs=user.getAccessibleOrganizations();
for(int j=0;j<deporgs.size();j++){
if(deporgs.get(j).getDbID()==org.getDbID()){
//mapping org belongs in deporgs so add
if(!maplist.contains(em)){
maplist.add(em);}
break;
}
Organization parent=deporgs.get(j).getParentalOrganization();
while(parent!=null && parent.getDbID()>0){
if(parent.getDbID()==org.getDbID()){
//mapping org belongs to parent of accessible so add
if(!maplist.contains(em)){
maplist.add(em);}
break;
}
parent=parent.getParentalOrganization();
//traverse all parents OMG
}
}
}
}
}
catch (Exception ex){
log.debug(" ERROR GETTING MAPPINGS:"+ex.getMessage());
}
if( maplist.isEmpty() ) maplist=Collections.emptyList();
return maplist;
}
public String getScene() {
return scene;
}
public void setScene(String scene) {
this.scene = scene;
if(SCENE_SELECT_MAPPING.equals( scene )){
this.setMappingSelector(true);
}
}
public List<PreviewTab> getTabs() {
return tabs;
}
public ArrayList<SAXParseException> getReport() {
return report;
}
public void setSelMapping(long selMapping) {
this.selMapping = selMapping;
}
public long getSelMapping(){
return selMapping;
}
public String getUploadId(){
return uploadId;
}
public void setUploadId(String uploadId){
this.uploadId=uploadId;
}
public String getNodeId(){
return nodeId;
}
public void setNodeId(String nodeId){
this.nodeId=nodeId;
}
public boolean isTruncated(){
return this.truncated;
}
public String toRDF( String xml ) throws Exception {
byte[] bytes = xml.getBytes();
InputStream inputStream = new ByteArrayInputStream(bytes);
gr.ntua.ivml.mint.rdf.edm.EDM2RDF xml2rdf = new gr.ntua.ivml.mint.rdf.edm.EDM2RDF(inputStream);
ByteArrayOutputStream outputStream = xml2rdf.convertToRDF();
return outputStream.toString();
}
public XMLNode getNode() {
XMLNode result = null;
if(( getNodeId() != null ) && ( getNodeId().trim().length() > 0 )) {
try {
long nodeId = Long.parseLong(getNodeId());
// if nodeId == 0 then get the first node from the data upload
if(nodeId == 0) {
DataUpload du = getDataUpload();
List<XMLNode> list = du.getItemXpath().getNodes(0, 1);
if(list != null && !list.isEmpty()) {
result = list.get(0);
}
} else {
XmlObject obj=getDataUpload().getXmlObject();
result = DB.getXMLNodeDAO().getByIdObject(obj,nodeId);
//result = DB.getXMLNodeDAO().getById(nodeId,false);
if(result.getSize()>20000){
truncated=true;
}
}
} catch( Exception e ) {
log.error( e );
}
}
return result;
}
public DataUpload getDataUpload() {
DataUpload result = null;
if(( getUploadId() != null ) &&
( getUploadId().trim().length() > 0 )) {
try {
long uploadId = Long.parseLong(getUploadId());
result = DB.getDataUploadDAO().getById(uploadId, false);
} catch( Exception e ) {
log.error( e );
}
}
return result;
}
public Mapping getMapping() {
if( getSelMapping() >01 ) {
try {
mapping = DB.getMappingDAO().getById(getSelMapping(), false);
} catch( Exception e ) {
log.error( e );
}
}
return mapping;
}
public void setMapping( Mapping m ) {
mapping = m;
}
public void setMappingSelector( boolean mappingSelector ) {
this.mappingSelector = mappingSelector;
}
public boolean getMappingSelector( ) {
return(this.mappingSelector );
}
/**
* Returns XML for selected Node.
* @return
*/
public String getItemPreview() {
if( ! hasItemPreview() ) return "";
StringWriter xmlWriter = new StringWriter();
XMLNode node = getNode();
node.toXmlWrapped(new PrintWriter(xmlWriter));
String xml = xmlWriter.toString();
xml = XMLFormatter.format(xml);
return xml;
}
public boolean hasItemPreview() {
return getNodeId()!=null;
}
/**
* Return transformed XML for selected node.
* Needs a selected mapping or DataUpload with
* finished transformation and a node.
* @return
*/
public String getValidation(String transformation){
try{
byte[] bytes = transformation.getBytes("UTF-8");
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
StreamSource source = new StreamSource(inputStream);
ReportErrorHandler reportHandler = new ReportErrorHandler();
SchemaValidator.validate( source, mapping.getTargetSchema(), reportHandler);
validation = reportHandler.getReportMessage();
report = reportHandler.getReport();
this.isValid = reportHandler.isValid();
} catch(Exception e) {
validation = e.getMessage();
this.isValid = false;
}
return validation;
}
public String getTransformPreview() {
DataUpload du = getDataUpload();
if(du.isDirect()) {
return getItemPreview();
} else {
String transformedItem=null;
if( !hasTransformPreview()) return "No transformed View available";
XSLTransform t = new XSLTransform();
try {
transformedItem = t.transform(getItemPreview(), getSchemaXsl());
transformedItem = XMLFormatter.format(transformedItem);
} catch( Exception e ) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter( sw );
e.printStackTrace(pw);
transformedItem = sw.toString();
}
return transformedItem;
}
}
public String getTransformedPreview() {
long nid=Long.parseLong(this.getNodeId());
XMLNode n = DB.getXMLNodeDAO().getById(nid, false);
StringWriter xmlWriter = new StringWriter();
String xml="";
try {
n.toXmlWrapped(new PrintWriter(xmlWriter));
xml = xmlWriter.toString();
xml = XMLFormatter.format(xml);
} catch( Exception e ) {
log.error( e );
}
return xml;
}
public boolean hasTransformPreview() {
if( getNode() == null ) return false;
if( getMapping() != null ) return true;
if( getDataUpload() == null ) return false;
// maybe the upload has been successfully transformed
List<Transformation> l = DB.getTransformationDAO().findByUpload( getDataUpload());
for( Transformation t: l ) {
if( t.getStatusCode() == Transformation.OK ) {
setMapping( t.getMapping());
return true;
}
}
return false;
}
/**
* Provide the Lido XSL for output. Needs to be able to find
* the Upload.
* @return
*/
public String getSchemaXsl() {
DataUpload du = getDataUpload();
XSLTGenerator xslt = new XSLTGenerator();
XpathHolder itemPath = du.getItemXpath();
String result = null;
if(!du.isDirect()) {
xslt.setItemLevel(itemPath.getXpathWithPrefix(true));
xslt.setTemplateMatch(itemPath.getXpathWithPrefix(true));
xslt.setImportNamespaces(du.getRootXpath().getNamespaces(true));
String mappings = getMapping().getJsonString();
String xsl = XMLFormatter.format(xslt.generateFromString(mappings));
result = xsl;
}
return result;
}
@Action(value="XMLPreview")
public String execute() throws Exception {
if( uploadId == null ) setError( "Missing uploadId parameter" );
if( nodeId == null) setError( "Missing nodeId parameter" );
if(this.hasActionErrors()){
return ERROR;
}
else{buildTabs();}
if(this.hasActionErrors()){
return ERROR;
}
else return SUCCESS;
}
/*
@Action(value="xmlPreviewInput")
public String previewInput() throws Exception {
log.debug( "Action: xmlPreviewInput");
if( uploadId == null ) setError( "Missing uploadId parameter" );
if( nodeId == null) setError( "Missing nodeId parameter" );
return "previewInput";
}
*/
@Action("XMLPreview_input")
@Override
public String input() throws Exception {
if( uploadId == null ) setError( "Missing uploadId parameter" );
if( nodeId == null) setError( "Missing nodeId parameter" );
if(this.hasActionErrors()){
return ERROR;
}
else{buildTabs();}
return super.input();
}
public void setError(String error) {
addActionError(error);
}
public String getError() {
return StringEscapeUtils.escapeHtml(error);
}
public boolean hasMappingSelector() {
return mappingSelector;
}
/**
* Overwrite and call super. Then modify the results as you like them.
*/
public void buildTabs() {
this.tabs = new ArrayList<PreviewTab>();
String output = null;
Mapping mapping = getMapping();
XmlSchema schema = null;
DataUpload du = getDataUpload();
if(du!=null){
if(du.isDirect()) {
schema = du.getDirectSchema();
} else if(mapping != null) {
schema = mapping.getTargetSchema();
} else if(du.getTransformations().size() > 0){
Transformation t = du.getTransformations().get(0);
if(t != null) {
schema = t.getMapping().getTargetSchema();
}
}
}
try {
if( SCENE_INPUT.equals( scene ) ) {
tabs.add( new PreviewTab( "Input", getItemPreview(), PreviewTab.TYPE_XML));
} else if( SCENE_SELECT_MAPPING.equals( scene )) {
if( selMapping ==0 ) {
setError("Please select a mapping");
}
else if(selMapping!=0 && (this.mapping==null || mapping.getJsonString().length()==0)){
setError( "Mappings selected are empty. Please define proper mappings.");
}
else {
tabs.add( new PreviewTab( "Input", getItemPreview(), PreviewTab.TYPE_XML));
tabs.add( new PreviewTab( "XSL", getSchemaXsl(), PreviewTab.TYPE_XML));
output=getTransformPreview();
tabs.add( new PreviewTab( "Output", output, PreviewTab.TYPE_XML));
tabs.add( new PreviewTab( "Validation", getValidation(output), PreviewTab.TYPE_TEXT));
}
} else if( SCENE_FIXED_MAPPING.equals( scene )) {
if(du.isDirect()) {
output = getItemPreview();
tabs.add( new PreviewTab( "Input", output, PreviewTab.TYPE_XML));
} else {
tabs.add( new PreviewTab( "Input", getItemPreview(), PreviewTab.TYPE_XML));
output = getTransformPreview();
tabs.add( new PreviewTab( "XSL", getSchemaXsl(), PreviewTab.TYPE_XML));
tabs.add( new PreviewTab( "Output", output, PreviewTab.TYPE_XML));
tabs.add( new PreviewTab( "Validation", getValidation(output), PreviewTab.TYPE_TEXT));
}
}
else if( SCENE_PUBLISHED_ERROR.equals( scene )) {
long nid=Long.parseLong(this.getNodeId());
output=this.getTransformedPreview();
tabs.add( new PreviewTab( "Transformed Item ", output, PreviewTab.TYPE_XML));
XmlObject xo = DB.getXmlObjectDAO().findByNodeId(nid);
if( xo != null ) {
Transformation tr = DB.getTransformationDAO().findByXmlObject( xo );
schema=tr.getMapping().getTargetSchema();
}
}
} catch( Exception e ) {
tabs.clear();
tabs.add( new PreviewTab( e ));
}
if(output != null && schema != null) {
ChainTransform chain = new ChainTransform();
try{
ArrayList<PreviewTab> more = chain.transform(output, schema);
tabs.addAll(more);
}catch (Exception ex){
log.debug(" ERROR on chain transform:"+ex.getMessage());
}
//log.debug(more);
}
}
public String exceptionTrace( Exception e ) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter( sw );
e.printStackTrace(pw);
return sw.toString();
}
@Override
public void setServletContext(ServletContext sc) {
this.sc = sc;
}
}