Package com.eviware.soapui.impl.wadl.inference.schema.types

Source Code of com.eviware.soapui.impl.wadl.inference.schema.types.ComplexType

/*
*  soapUI, copyright (C) 2004-2011 eviware.com
*
*  soapUI is free software; you can redistribute it and/or modify it under the
*  terms of version 2.1 of the GNU Lesser General Public License as published by
*  the Free Software Foundation.
*
*  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
*  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*  See the GNU Lesser General Public License for more details at gnu.org.
*/

package com.eviware.soapui.impl.wadl.inference.schema.types;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;

import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.SchemaTypeSystem;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;

import com.eviware.soapui.impl.wadl.inference.ConflictHandler;
import com.eviware.soapui.impl.wadl.inference.schema.Content;
import com.eviware.soapui.impl.wadl.inference.schema.Context;
import com.eviware.soapui.impl.wadl.inference.schema.Particle;
import com.eviware.soapui.impl.wadl.inference.schema.Schema;
import com.eviware.soapui.impl.wadl.inference.schema.Settings;
import com.eviware.soapui.impl.wadl.inference.schema.Type;
import com.eviware.soapui.impl.wadl.inference.schema.content.EmptyContent;
import com.eviware.soapui.inferredSchema.ComplexTypeConfig;
import com.eviware.soapui.inferredSchema.ParticleConfig;
import com.eviware.soapui.inferredSchema.TypeReferenceConfig;

/**
* ComplexType corresponds to an xs:complexType. It's definition is displayed in
* the schema for which it belongs.
*
* @author Dain Nilsson
*/
public class ComplexType implements Type
{
  private String name;
  private Schema schema;
  private Map<QName, Particle> attributes;
  private Content content;
  private boolean mixed = false;
  private boolean completed = false;

  public ComplexType( Schema schema, String name, boolean completed )
  {
    this.schema = schema;
    this.name = name;
    this.completed = completed;
    content = new EmptyContent( schema, completed );
    attributes = new HashMap<QName, Particle>();
    schema.addType( this );
  }

  public ComplexType( ComplexTypeConfig xml, Schema schema )
  {
    this.schema = schema;
    name = xml.getName();
    completed = xml.getCompleted();
    mixed = xml.getMixed();
    content = Content.Factory.parse( xml.getContent(), schema );
    attributes = new HashMap<QName, Particle>();
    for( ParticleConfig item : xml.getAttributeList() )
    {
      Particle p = Particle.Factory.parse( item, schema );
      attributes.put( new QName( "", p.getName().getLocalPart() ), p );
    }
    schema.addType( this );
  }

  public void save( ComplexTypeConfig xml )
  {
    xml.setName( name );
    xml.setCompleted( completed );
    xml.setMixed( mixed );
    List<ParticleConfig> particleList = new ArrayList<ParticleConfig>();
    for( Particle item : attributes.values() )
      particleList.add( item.save() );
    xml.setAttributeArray( particleList.toArray( new ParticleConfig[0] ) );
    xml.setContent( content.save() );
  }

  public TypeReferenceConfig save()
  {
    TypeReferenceConfig xml = TypeReferenceConfig.Factory.newInstance();
    xml.setReference( new QName( schema.getNamespace(), name ) );
    return xml;
  }

  public void setContent( Content content )
  {
    this.content = content;
  }

  public Type validate( Context context ) throws XmlException
  {
    XmlCursor cursor = context.getCursor();
    List<QName> seen = new ArrayList<QName>();
    cursor.push();
    if( !mixed && isMixed( context ) )
    {
      // TODO: Check with ConflictHandler
      mixed = true;
    }
    cursor.pop();
    cursor.push();
    if( cursor.toFirstAttribute() )
    {
      do
      {
        QName qname = cursor.getName();
        if( attributes.containsKey( qname ) )
        {
          attributes.get( qname ).validate( context );
        }
        else if( qname.getNamespaceURI().equals( Settings.xsins ) )
        {
          // Ignore
        }
        else if( context.getHandler().callback( ConflictHandler.Event.CREATION, ConflictHandler.Type.ATTRIBUTE,
            new QName( schema.getNamespace(), qname.getLocalPart() ), context.getPath(), "Undeclared attribute." ) )
        {
          if( qname.getNamespaceURI().equals( schema.getNamespace() ) || qname.getNamespaceURI().equals( "" ) )
          {
            newAttribute( qname ).validate( context );
          }
          else
          {
            Schema otherSchema = context.getSchemaSystem().getSchemaForNamespace( qname.getNamespaceURI() );
            schema.putPrefixForNamespace( qname.getPrefix(), qname.getNamespaceURI() );
            if( otherSchema == null )
            {
              otherSchema = context.getSchemaSystem().newSchema( qname.getNamespaceURI() );
            }
            Particle ref = otherSchema.getParticle( qname.getLocalPart() );
            if( ref == null )
            {
              ref = otherSchema.newAttribute( qname.getLocalPart() );
            }
            if( completed )
              ref.setAttribute( "use", "optional" );
            Particle newAttribute = Particle.Factory.newReferenceInstance( schema, ref );
            attributes.put( qname, newAttribute );
            newAttribute.validate( context );
          }
        }
        else
          throw new XmlException( "Illegal attribute!" );
        seen.add( qname );
      }
      while( cursor.toNextAttribute() );
    }
    // Make sure all attributes have been accounted for
    for( QName item : attributes.keySet() )
    {
      if( !seen.contains( item ) && !attributes.get( item ).getAttribute( "use" ).equals( "optional" ) )
      {
        if( context.getHandler().callback( ConflictHandler.Event.MODIFICATION, ConflictHandler.Type.ATTRIBUTE,
            item, context.getPath(), "Required attribute missing." ) )
        {
          attributes.get( item ).setAttribute( "use", "optional" );
        }
        else
          throw new XmlException( "Required attribute missing!" );
      }
    }
    cursor.pop();
    if( !cursor.toFirstChild() )
      cursor.toFirstContentToken();
    if( !context.getAttribute( "nil" ).equals( "true" ) )
      validateContent( context );
    completed = true;
    return this;
  }

  private void validateContent( Context context ) throws XmlException
  {
    context.getCursor().push();
    context.putAttribute( "typeName", name );
    Content newContent = content.validate( context );
    context.clearAttribute( "typeName" );
    if( content != newContent )
    {
      String problem = "Illegal content for complexType '" + name + "'.";
      if( context.getHandler().callback( ConflictHandler.Event.MODIFICATION, ConflictHandler.Type.TYPE,
          new QName( schema.getNamespace(), name ), context.getPath(), "Illegal complex content." ) )
      {
        content = newContent;
        context.getCursor().pop();
        validateContent( context );
        return;
      }
      else
        throw new XmlException( problem );
    }
    context.getCursor().pop();
  }

  private boolean isMixed( Context context )
  {
    QName name = context.getCursor().getName();
    SchemaTypeSystem sts;
    try
    {
      sts = XmlBeans.compileXsd( new XmlObject[] { XmlObject.Factory
          .parse( "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"" + name.getNamespaceURI()
              + "\" targetNamespace=\"" + name.getNamespaceURI() + "\">" + "<xs:element name=\""
              + name.getLocalPart() + "\"><xs:complexType><xs:sequence>"
              + "<xs:any processContents=\"skip\" minOccurs=\"0\" maxOccurs=\"unbounded\" /></xs:sequence>"
              + "<xs:anyAttribute processContents=\"skip\"/></xs:complexType></xs:element></xs:schema>" ) },
          XmlBeans.getBuiltinTypeSystem(), null );
      SchemaTypeLoader stl = XmlBeans
          .typeLoaderUnion( new SchemaTypeLoader[] { sts, XmlBeans.getBuiltinTypeSystem() } );
      if( !stl.parse( context.getCursor().xmlText(), null, null ).validate() )
        return true;
    }
    catch( XmlException e )
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return false;
  }

  public String getName()
  {
    return name;
  }

  public Schema getSchema()
  {
    return schema;
  }

  public void setSchema( Schema schema )
  {
    this.schema = schema;
  }

  @Override
  public String toString()
  {
    String xsdns = schema.getPrefixForNamespace( Settings.xsdns );
    StringBuilder s = new StringBuilder( "<" + xsdns + ":complexType name=\"" + name + "\"" );
    if( mixed )
      s.append( " mixed=\"true\"" );
    s.append( ">" );
    StringBuilder attrs = new StringBuilder();
    for( Particle item : attributes.values() )
    {
      attrs.append( item );
    }
    s.append( content.toString( attrs.toString() ) );
    s.append( "</" + xsdns + ":complexType>" );
    return s.toString();
  }

  private Particle newAttribute( QName qname )
  {
    Particle p = Particle.Factory.newAttributeInstance( schema, qname.getLocalPart() );
    attributes.put( qname, p );
    if( completed )
      p.setAttribute( "use", "optional" );
    return p;
  }

}
TOP

Related Classes of com.eviware.soapui.impl.wadl.inference.schema.types.ComplexType

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.