Coverage Report - uk.co.badgersinfoil.asxsd.components.MultiplyOccuringParticleComponent
 
Classes in this File Line Coverage Branch Coverage Complexity
MultiplyOccuringParticleComponent
98% 
100% 
2.167
 
 1  
 /*
 2  
  * Copyright (c) 2007 David Holroyd
 3  
  */
 4  
 
 5  
 package uk.co.badgersinfoil.asxsd.components;
 6  
 
 7  
 import org.eclipse.xsd.XSDConcreteComponent;
 8  
 import org.eclipse.xsd.XSDParticle;
 9  
 import org.eclipse.xsd.XSDParticleContent;
 10  
 import uk.co.badgersinfoil.asxsd.CodegenContext;
 11  
 import uk.co.badgersinfoil.asxsd.CodegenRole;
 12  
 import uk.co.badgersinfoil.asxsd.MappingFunction;
 13  
 import uk.co.badgersinfoil.asxsd.MarshalBuilder;
 14  
 import uk.co.badgersinfoil.asxsd.TypeBuilder;
 15  
 import uk.co.badgersinfoil.asxsd.TypeDescriptor;
 16  
 import uk.co.badgersinfoil.asxsd.UnmarshalBuilder;
 17  
 import uk.co.badgersinfoil.metaas.ActionScriptFactory;
 18  
 import uk.co.badgersinfoil.metaas.dom.ASClassType;
 19  
 import uk.co.badgersinfoil.metaas.dom.ASCompilationUnit;
 20  
 import uk.co.badgersinfoil.metaas.dom.ASConstants;
 21  
 import uk.co.badgersinfoil.metaas.dom.ASExpression;
 22  
 import uk.co.badgersinfoil.metaas.dom.ASField;
 23  
 import uk.co.badgersinfoil.metaas.dom.StatementContainer;
 24  
 import uk.co.badgersinfoil.metaas.dom.Visibility;
 25  
 
 26  
 
 27  16
 public class MultiplyOccuringParticleComponent extends AbstractParticleComponent {
 28  
 
 29  
         protected TypeDescriptor createTypeDescriptor(CodegenContext context, XSDParticle particle) {
 30  2
                 TypeDescriptor elementType = context.typeDescriptorFor(particle.getContent());
 31  2
                 String doc = "Elements of type {@link " + elementType.getTypeName() + "}";
 32  2
                 if (particle.getMinOccurs()!=0 || particle.getMaxOccurs()!=-1) {
 33  2
                         doc += " (minimum "+describeMultiplicity(particle.getMinOccurs())+", maximum "+describeMultiplicity(particle.getMaxOccurs())+")";
 34  
                 }
 35  2
                 return new TypeDescriptor(ASConstants.TYPE_ARRAY, true, doc, particle);
 36  
         }
 37  
 
 38  
         public ASCompilationUnit createType(CodegenContext context,
 39  
                                          XSDConcreteComponent component)
 40  
         {
 41  2
                 return null;
 42  
         }
 43  
 
 44  
         /**
 45  
          * returns a text string with either the value "unbounded" if the
 46  
          * given integer is -1, or the decimal representation of the given
 47  
          * integer otherwise.
 48  
          */
 49  
         private static String describeMultiplicity(int occurs) {
 50  4
                 if (occurs == -1) {
 51  2
                         return "unbounded";
 52  
                 } else {
 53  2
                         return String.valueOf(occurs);
 54  
                 }
 55  
         }
 56  
 
 57  
         protected boolean willAcceptParticle(XSDParticle particle) {
 58  60
                 return particle.getMaxOccurs() != 1;
 59  
         }
 60  
 
 61  
         protected void generateCodeFor(CodegenContext context,
 62  
                                        XSDParticle particle)
 63  
         {
 64  6
                 CodegenRole role = context.getCurrentRole();
 65  6
                 XSDParticleContent content = particle.getContent();
 66  6
                 if (role == CodegenRole.UNMARSHAL) {
 67  2
                         StatementContainer block = context.getCurrentMethodCode();
 68  2
                         String fieldAccess = "_result." + context.variableNameFor(content);
 69  2
                         String accessExpr = UnmarshalBuilder.getCurrentSourceExpr(context);
 70  2
                         MappingFunction unmarshaler = context.functionFor(content);
 71  2
                         block.addStmt(fieldAccess + "= new Array()");
 72  2
                         ActionScriptFactory fact = context.getFactory();
 73  2
                         ASExpression childLimit = fact.newExpression("_seq<_children.length()");
 74  2
                         ASExpression detect = detect(context, content);
 75  2
                         ASExpression conditional = fact.newAndExpression(childLimit, detect);
 76  2
                         block = block.newWhile(conditional);
 77  2
                         block.addStmt(fieldAccess + ".push(" + unmarshaler.appliedTo(accessExpr) + ")");
 78  2
                 } else if (role == CodegenRole.MARSHAL) {
 79  2
                         StatementContainer containingBlock = context.getCurrentMethodCode();
 80  2
                         String propertyName = context.variableNameFor(content);
 81  2
                         String childVarName = propertyName + "_child";
 82  2
                         String sourceExpr = MarshalBuilder.getCurrentSourceExpr(context);
 83  2
                         String accessExpr = sourceExpr+"."+propertyName;
 84  2
                         TypeDescriptor typeDesc = context.typeDescriptorFor(content);
 85  2
                         String typeName = typeDesc.getTypeName();
 86  2
                         StatementContainer forEachBlock = containingBlock.newForEachIn("var "+childVarName+":"+typeName, accessExpr);
 87  2
                         context.pushAttrScope();
 88  2
                         context.setCurrentMethodCode(forEachBlock);
 89  2
                         MarshalBuilder.setCurrentSourceExpr(context, childVarName);
 90  
 
 91  2
                         context.generateCode(content);
 92  
 
 93  
                         // switch back to the original block,
 94  2
                         context.popAttrScope();
 95  2
                 } else if (role == CodegenRole.TYPE) {
 96  2
                         ASCompilationUnit unit = TypeBuilder.getCurrentTypeCompilationUnit(context);
 97  2
                         ASClassType clazz = (ASClassType)unit.getType();
 98  2
                         TypeDescriptor typeDesc = context.typeDescriptorFor(particle);
 99  2
                         ASField field = clazz.newField(context.variableNameFor(content), Visibility.PUBLIC, typeDesc.getTypeName());
 100  2
                         field.setDescription(typeDesc.getDocumentation());                        
 101  2
                 } else {
 102  0
                         throw new RuntimeException(getClass().getName()+" does not suppport operation generateCodeFor(role="+role+")");
 103  
                 }
 104  6
         }
 105  
 
 106  
         private ASExpression detect(CodegenContext context,
 107  
                                     XSDParticleContent content)
 108  
         {
 109  2
                 context.pushAttrScope();
 110  2
                 context.setCurrentRole(CodegenRole.UNMARSHAL_DETECT);
 111  2
                 ASExpression detect = context.createExpression(content);
 112  2
                 context.popAttrScope();
 113  2
                 return detect;
 114  
         }
 115  
 }