package openadk.library.impl.surrogates; import javax.xml.stream.XMLStreamReader; import org.apache.commons.jxpath.JXPathContext; import org.apache.commons.jxpath.ri.QName; import org.apache.commons.jxpath.ri.model.NodeIterator; import org.apache.commons.jxpath.ri.model.NodePointer; import openadk.library.*; import openadk.library.common.PartialDateType; import openadk.library.student.StudentDTD; import openadk.library.tools.xpath.SIFElementPointer; import openadk.util.XMLWriter; /** * RenderSurrogate that renders and parses the SIF 1.5r1 and SIF 1.1 GradYear * elements into their SIF 2.0 format * @author Andrew * */ public class GradYearSurrogate extends AbstractRenderSurrogate implements RenderSurrogate { // TODO: This class would be much more streamlined if we had better support // in SIFXPathContext for using SIF 2.0 xpaths while working with a 1.x object public GradYearSurrogate( ElementDef def ){ super( def ); } public void renderRaw(XMLWriter writer, SIFVersion version, Element o, SIFFormatter formatter) throws SIFException { String type = getTypeAttribute(); String value = null; if( type == "Actual" ){ PartialDateType gradDate = (PartialDateType)o; Integer year = gradDate.getYear(); if( year == null ) { value = ""; } else { value = String.format( "%04d", year.intValue() ); } } else { value = o.getTextValue(); if( value == null ){ // in SIF 1.5, represent null values as "" value = ""; } } if( type != null && value != null ){ // try // { writer.tab(); writer.write( "<GradYear Type=\"" ); writer.write( type ); writer.write( "\">" ); writer.write( value ); writer.write( "</GradYear>" ); writer.write( "\r\n" ); //} // catch( XMLStreamException xse ) // { // throwSIFException( xse, "", version ); // } } } private String getTypeAttribute() { if( fElementDef.name().equals( "ProjectedGraduationYear" ) ){ return "Projected"; } else if ( fElementDef.name().equals( "OnTimeGraduationYear" ) ){ return "Original"; } else if ( fElementDef.name().equals( "PartialDateType" ) ){ return "Actual"; } return ""; } public boolean readRaw(XMLStreamReader reader, SIFVersion version, SIFElement parent, SIFFormatter formatter) throws ADKParsingException { if( !reader.getLocalName().equals( "GradYear" ) ){ return false; } // // NOTE: // GradYear can appear on both StudentPersonal and StudentSnapshot // String type = reader.getAttributeValue( null, "Type" ); String value = consumeElementTextValue( reader, version ); ElementDef childDef = null; if( type != null && value != null ) { SIFInt intValue = (SIFInt)SIFTypeConverters.INT.parse( formatter, value ); Integer year = intValue.getValue(); if( "Projected".equals( type ) ){ childDef = ADK.DTD().lookupElementDef( parent.getElementDef(), "ProjectedGraduationYear" ); parent.setField( childDef, intValue ); } else if( "Original".equals( type ) ){ childDef = ADK.DTD().lookupElementDef( parent.getElementDef(), "OnTimeGraduationYear" ); parent.setField( childDef, intValue ); } else { childDef = ADK.DTD().lookupElementDef( parent.getElementDef(), "GraduationDate" ); PartialDateType gd = new PartialDateType( year ); parent.addChild( childDef, gd ); } } return true; } /* (non-Javadoc) * @see openadk.library.impl.surrogates.RenderSurrogate#createChild(org.apache.commons.jxpath.ri.model.NodePointer, openadk.library.SIFFormatter, openadk.library.SIFVersion, org.apache.commons.jxpath.JXPathContext) */ public NodePointer createChild(NodePointer parentPointer, SIFFormatter formatter, SIFVersion version, JXPathContext context ) { return new GradYearNodePointer( parentPointer ); } /* (non-Javadoc) * @see openadk.library.impl.surrogates.RenderSurrogate#getPath() */ public String getPath() { return "GradYear[@Type='" + getTypeAttribute() + "']"; } /* (non-Javadoc) * @see openadk.library.impl.surrogates.RenderSurrogate#createNodePointer(org.apache.commons.jxpath.ri.model.NodePointer, openadk.library.Element, openadk.library.SIFVersion) */ public NodePointer createNodePointer(NodePointer parent, Element element, SIFVersion version) { ElementDef def = element.getElementDef(); if( def.name().equals( StudentDTD.STUDENTPERSONAL_PROJECTEDGRADUATIONYEAR.name() ) ){ return new GradYearNodePointer(parent, element, "Projected" ); } else if( def.name().equals( StudentDTD.STUDENTPERSONAL_ONTIMEGRADUATIONYEAR.name() ) ){ return new GradYearNodePointer(parent, element, "Original" ); } else if( def.name().equals( StudentDTD.STUDENTPERSONAL_GRADUATIONDATE.name() ) ){ return new GradYearNodePointer(parent, element, "Actual" ); } return null; } /** * Implements a node pointer that represents a GradYear element. This node * pointer is created based on a legacy XPath, such as GradYear[@Type='Projected']. * The actual node this class points to, however, would be the field on StudentPersonal * or StudentSnapshot that represents the Projected Grad Year. For StudentPersonal, * that field is the OnTimeGraduationYear element. * @author Andrew Elmhorst * */ class GradYearNodePointer extends SurrogateElementPointer<Element> { /** * */ private static final long serialVersionUID = 8441111097610733968L; /** * The string that represents the GradYear/@Type value of this element * in SIF 1.x versions */ private String fAttrValue; protected GradYearNodePointer(NodePointer parentPointer ) { super(parentPointer, "GradYear" ); } protected GradYearNodePointer(NodePointer parentPointer, Element field, String attrValue ) { super(parentPointer, "GradYear", field ); fAttrValue = attrValue; } @Override public NodeIterator attributeIterator(QName qname) { if( qname.getName().equals( "Type" ) ){ return new FauxAttribute( this, "Type", fAttrValue ); } return null; } @Override public NodePointer createAttribute(JXPathContext context, QName name) { return new GradYearTypePointer( this ); } @Override public boolean isLeaf() { return true; } @Override public void setValue(Object value) { SIFSimpleType<Integer> sifValue = null; if( value instanceof SIFInt ){ sifValue = (SIFInt)value; } else { sifValue = SIFTypeConverters.INT.getSIFSimpleType( value ); } Element e = getElement(); if( e instanceof PartialDateType ){ ((PartialDateType)e).setYear( sifValue.getValue() ); } else { e.setSIFValue( sifValue ); } } @SuppressWarnings("unchecked") void setGradYearType( String type ){ fAttrValue = type; SIFElementPointer parentPointer = (SIFElementPointer)getParent(); SIFElement sp = (SIFElement)parentPointer.getBaseValue(); SIFSimpleType nullValue = SIFTypeConverters.INT.getSIFSimpleType( null ); Element field = null; if( type.equals( "Projected" ) ){ field = sp.getField( "ProjectedGraduationYear" ); if( field == null ){ ElementDef childDef = ADK.DTD().lookupElementDef( sp.getElementDef(), "ProjectedGraduationYear" ); field = sp.setField( childDef, nullValue ); } } else if( type.equals( "Original" ) ){ field = sp.getField( "OnTimeGraduationYear" ); if( field == null ){ ElementDef childDef = ADK.DTD().lookupElementDef( sp.getElementDef(), "OnTimeGraduationYear" ); field = sp.setField( childDef, nullValue ); } } else { PartialDateType gd = new PartialDateType( (String)null ); ElementDef childDef = ADK.DTD().lookupElementDef( sp.getElementDef(), "GraduationDate" ); sp.addChild( childDef, gd ); field = gd; } setElement( field ); } /** * Represents a temporary in-memory pointer to the @Type attribute * of the GradYear element. This element does not exist in the ADK, * but a pointer to it is allowed, since the ADK supports SIF 1.x * XPaths. * @author Andy Elmhorst * */ class GradYearTypePointer extends FauxElementPointer { /** * */ private static final long serialVersionUID = 4550174490811773922L; protected GradYearTypePointer(NodePointer parentPointer) { super(parentPointer, "Type"); } @Override public boolean isLeaf() { return true; } @Override public Object getBaseValue() { // TODO Auto-generated method stub return null; } @Override public Object getImmediateNode() { // TODO Auto-generated method stub return null; } @Override public void setValue(Object value) { setGradYearType( value.toString() ); } } } }