Thread: [Icamodel-commits] icamodel/src/icamodel/framework BusinessLine.java, 1.2, 1.3 ModelBit.java, 1.3,
Brought to you by:
lmpryor
From: Louise P. <lm...@us...> - 2007-06-24 16:09:37
|
Update of /cvsroot/icamodel/icamodel/src/icamodel/framework In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv8442/src/icamodel/framework Modified Files: BusinessLine.java ModelBit.java Parameters.java RandomNumberGenerator.java Log Message: XML parameter file. Needed to standardise some things: All ModelBits must have 1-arg constructor All parameter setting must be via single arg setter Index: ModelBit.java =================================================================== RCS file: /cvsroot/icamodel/icamodel/src/icamodel/framework/ModelBit.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** ModelBit.java 23 Jun 2007 18:20:47 -0000 1.3 --- ModelBit.java 24 Jun 2007 16:09:35 -0000 1.4 *************** *** 28,31 **** --- 28,33 ---- * Basic model element. A node in the tree. This just provides the basic * mechanism. Concrete subclasses must override the abstract methods. + * Subclasses must be in package icamodel.bits (else they won't be found when we parse the parameter file). + * they must also have a constructor that takes a single string argument (the name). * * @author Louise Index: RandomNumberGenerator.java =================================================================== RCS file: /cvsroot/icamodel/icamodel/src/icamodel/framework/RandomNumberGenerator.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** RandomNumberGenerator.java 16 May 2007 16:42:31 -0000 1.3 --- RandomNumberGenerator.java 24 Jun 2007 16:09:35 -0000 1.4 *************** *** 12,16 **** /** ! * something that'll get random numbers for us * @author Louise */ --- 12,18 ---- /** ! * something that'll get random numbers for us. ! * Subclasses must be in package icamodel.utils (else they won't be found when we parse the parameter file). ! * They must also have a default constructor (ie, one without arguments). * @author Louise */ Index: Parameters.java =================================================================== RCS file: /cvsroot/icamodel/icamodel/src/icamodel/framework/Parameters.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Parameters.java 24 Jun 2007 10:45:15 -0000 1.1 --- Parameters.java 24 Jun 2007 16:09:35 -0000 1.2 *************** *** 11,20 **** --- 11,33 ---- package icamodel.framework; + import icamodel.bits.Assets; + import icamodel.bits.External; + import icamodel.bits.Liabilities; + import icamodel.bits.ModelRoot; + import icamodel.utils.InitialisationException; + import icamodel.utils.ModelException; + import icamodel.utils.PaymentPattern; import java.io.File; import java.io.IOException; + import java.lang.reflect.Constructor; + import java.lang.reflect.InvocationTargetException; + import java.lang.reflect.Method; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; + import org.w3c.dom.Element; + import org.w3c.dom.Node; + import org.w3c.dom.NodeList; import org.xml.sax.SAXException; *************** *** 77,83 **** /** * build our model from the Document that's been created */ ! public void buildModel() { } } --- 90,496 ---- /** * build our model from the Document that's been created + * hard code in the (required) top level nodes. All others are + * done as generic ModelBits. */ ! public void buildModel() throws InitialisationException, ModelException { ! ! // we expect the root to be <model> and there to be only one of them ! NodeList kids = paramTree.getChildNodes(); ! Node kid = null; ! for (int i=0; i<kids.getLength(); i++) { ! if (kids.item(i).getNodeType() == Node.ELEMENT_NODE) { ! if (kid != null) { ! // we already have an element. Something has gone wrong ! throw new InitialisationException("Your model must have only one root."); ! } else { ! kid = kids.item(i); ! } ! } else if (kids.item(i).getNodeType() != Node.COMMENT_NODE && ! kids.item(i).getNodeType() != Node.TEXT_NODE) { ! throw new InitialisationException("Unexpected entry: " + kids.item(i)); ! } ! } ! ! Element modelElement = (Element) kid; ! if (modelElement.getTagName() != "model") { ! throw new InitialisationException("The model root must be a <model> element. Your file has <" + ! modelElement.getTagName() +">."); ! } ! ! // OK, we're OK so far. ! kids = modelElement.getChildNodes(); ! ModelRoot root = ModelRoot.getInstance(); ! // It should have some parameters ! setParameters( root, kids); ! ! // now we do the children: External, Liabilities, Assets, Corporate, BusinessLogic ! Element extElement = null; ! Element liabElement = null; ! Element assElement = null; ! Element corpElement = null; ! Element busElement = null; ! for (int i=0; i < kids.getLength(); i++) { ! if (kids.item(i).getNodeType() != Node.ELEMENT_NODE ) { ! continue; // skip this one ! } ! Element elt = (Element) kids.item(i); ! if (elt.getTagName().equals("external")) { ! if (extElement != null) { ! throw new InitialisationException("You have more than one <external> node."); ! } ! extElement = elt; ! } else if (elt.getTagName().equals("liabilities")) { ! if (liabElement != null) { ! throw new InitialisationException("You have more than one <liabilities> node."); ! } ! liabElement = elt; ! } else if (elt.getTagName().equals("assets")) { ! if (assElement != null) { ! throw new InitialisationException("You have more than one <assets> node."); ! } ! assElement = elt; ! } else if (elt.getTagName().equals("corporate")) { ! if (corpElement != null) { ! throw new InitialisationException("You have more than one <corporate> node."); ! } ! corpElement = elt; ! } else if (elt.getTagName().equals("businessLogic")) { ! if (busElement != null) { ! throw new InitialisationException("You have more than one <businessLogic> node."); ! } ! busElement = elt; ! } else if (elt.getTagName().equals("param")){ ! continue; // not interested in this one ! } else { ! throw new InitialisationException("Unexpected tag: <elt.getTagName()>."); ! } ! } // we've now dealt with all the Element children ! ! // do the External one. ! if (extElement != null) { ! buildExternalModelBit(extElement); ! } ! // do the Liabilities one. ! if (liabElement != null) { ! buildLiabilitiesModelBit(liabElement); ! } ! // do the Assets one. ! if (assElement != null) { ! buildAssetsModelBit(assElement); ! } ! } ! ! /** ! * We expect a random number generator, plus ModelBit children. No parameters at present, but ! * there might be later ! */ ! private static void buildExternalModelBit(Element extElement) ! throws InitialisationException, ModelException { ! External ext = External.getInstance(); ! NodeList kids = extElement.getChildNodes(); ! setParameters(ext, kids); ! for (int i = 0; i < kids.getLength(); i++) { ! if (kids.item(i).getNodeType() != Node.ELEMENT_NODE ) { ! continue; // skip this one ! } ! Element kid = (Element) kids.item(i); ! if (kid.getTagName().equals("randomNumberGenerator")) { ! buildRandomNumberGenerator(ext, kid); ! } else if (kid.getTagName().equals("modelBit")) { ! addModelBit(ext, kid); ! } else if (kid.getTagName().equals("param")) { ! continue; ! } else { ! throw new InitialisationException("Unrecognised tag <" + kid.getTagName() + ">"); ! } ! } ! } ! ! /** ! * We only expect params and modelBits ! */ ! private static void buildLiabilitiesModelBit(Element liabElement) ! throws InitialisationException, ModelException { ! ! Liabilities liabs = Liabilities.getInstance(); ! NodeList kids = liabElement.getChildNodes(); ! setParameters(liabs, kids); ! for (int i = 0; i < kids.getLength(); i++) { ! if (kids.item(i).getNodeType() != Node.ELEMENT_NODE ) { ! continue; // skip this one ! } ! Element kid = (Element) kids.item(i); ! if (kid.getTagName().equals("modelBit")) { ! addModelBit(liabs, kid); ! } else if (kid.getTagName().equals("param")) { ! continue; ! } else { ! throw new InitialisationException("Unrecognised tag <" + kid.getTagName() + ">"); ! } ! } ! ! } ! /** ! * We only expect params and modelBits ! */ ! private static void buildAssetsModelBit(Element assElement) ! throws InitialisationException, ModelException { ! ! Assets assets = Assets.getInstance(); ! NodeList kids = assElement.getChildNodes(); ! setParameters(assets, kids); ! for (int i = 0; i < kids.getLength(); i++) { ! if (kids.item(i).getNodeType() != Node.ELEMENT_NODE ) { ! continue; // skip this one ! } ! Element kid = (Element) kids.item(i); ! if (kid.getTagName().equals("modelBit")) { ! addModelBit(assets, kid); ! } else if (kid.getTagName().equals("param")) { ! continue; ! } else { ! throw new InitialisationException("Unrecognised tag <" + kid.getTagName() + ">"); ! } ! } } + + private static void buildRandomNumberGenerator(External ext, Element rngElement) + throws InitialisationException { + + String rngType = rngElement.getAttribute("type"); + if (rngType == "") { + throw new InitialisationException("<randomNumberGenerator> element must have a type"); + } + Class<?> rngClass = null; + try { + rngClass = Class.forName("icamodel.utils." + rngType); + } catch (ClassNotFoundException ex) { + throw new InitialisationException("Invalid type for random number generator: " + rngType, ex); + } + Object rng = null; + try { + rng = rngClass.newInstance(); + } catch (InstantiationException ex) { + throw new InitialisationException("Problem making object of class " + rngType); + } catch (IllegalAccessException ex) { + throw new InitialisationException("Problem making object of class " + rngType); + } + // check that it is a subclass of RandomNumberGenerator + if (! (rng instanceof RandomNumberGenerator)) { + throw new InitialisationException(rngType + " is not a valid random number generator."); + } + setParameters(rng, rngElement.getChildNodes()); + ext.setRandomNumberGenerator((RandomNumberGenerator) rng); + } + + /** + * A modelBit tag can contain other modelBit tags and param tags. + */ + private static void addModelBit(ModelBit parent, Element mbElement) + throws InitialisationException, ModelException { + String mbName = mbElement.getAttribute("name"); + if (mbName == "") { + throw new InitialisationException("<modelBit> element must have a name"); + } + String mbType = mbElement.getAttribute("type"); + if (mbType == "") { + throw new InitialisationException(mbName + ": <modelBit> element must have a type"); + } + Class<?> mbClass = null; + try { + mbClass = Class.forName("icamodel.bits." + mbType); + } catch (ClassNotFoundException ex) { + throw new InitialisationException("Invalid type for modelBit: " + mbType, ex); + } + Constructor<?> mbConstructor = null; + try { + mbConstructor = mbClass.getConstructor(String.class); + } catch (NoSuchMethodException ex) { + throw new InitialisationException("Can't create instance of " + mbType, ex); + } + Object mbObj = null; + try { + mbObj = mbConstructor.newInstance(mbName); + } catch (InstantiationException ex) { + throw new InitialisationException("Can't create instance of " + mbType, ex); + } catch (IllegalAccessException ex) { + throw new InitialisationException("Can't create instance of " + mbType, ex); + } catch (InvocationTargetException ex) { + throw new InitialisationException("Can't create instance of " + mbType, ex); + } + if (! (mbObj instanceof ModelBit)) { + throw new InitialisationException("Invalid type for modelBit: " + mbType); + } + + ModelBit mBit = (ModelBit) mbObj; + // We've created the object and it is a model bit + // Now set its parameters, then add it to the tree. + // finally, do its children. + NodeList kids = mbElement.getChildNodes(); + setParameters(mbObj, kids); + parent.addChild(mBit); + + for (int i = 0; i < kids.getLength(); i++) { + if (kids.item(i).getNodeType() != Node.ELEMENT_NODE ) { + continue; // skip this one + } + Element kid = (Element) kids.item(i); + if (kid.getTagName().equals("modelBit")) { + addModelBit(mBit, kid); + } else if (kid.getTagName().equals("param")) { + continue; + } else { + throw new InitialisationException("Unrecognised tag <" + kid.getTagName() + ">"); + } + } + } + /** + * set some parameters of an object (usually a ModelBit). + * the id attribute of the element says what method to use + * the type attribute says how to interpret the value + * the text inside the element is the value + * TODO: more useful error messages + **/ + private static void setParameters(Object mBit, NodeList paramElements) throws InitialisationException { + // first we get all the methods that the modelBit has + Class<?> mClass = mBit.getClass(); + Method[] meths = mClass.getMethods(); + + // now go through the params + int paramCount = paramElements.getLength(); + for (int i=0; i < paramCount; i++) { + if (paramElements.item(i).getNodeType() != Node.ELEMENT_NODE ) { + continue; // skip this one + } + Element paramElt = (Element) paramElements.item(i); + if (! paramElt.getTagName().equals("param")) { + continue; // not interested in this one + } + setParameter(mBit, paramElt, meths); + } + } + + private static void setParameter(Object mBit, Element paramElt, Method[] meths) throws InitialisationException { + String id = paramElt.getAttribute("id"); + if (id == "") { + throw new InitialisationException("<param> element must have an id"); + } + Method setterMethod = null; + for (int j=0; j< meths.length; j++) { + Method thisMethod = meths[j]; + if (thisMethod.getName().equals("set" + id)) { + setterMethod = thisMethod; + break; + } + } + if (setterMethod == null) { + throw new InitialisationException("Invalid id in <param> element (" + id + ")."); + } + // OK, we've got a method. Now let's try to use it + Object realVal = getTypedParamValue(paramElt); + // apply + try { + setterMethod.invoke(mBit, realVal); + } catch (IllegalAccessException ex) { + throw new InitialisationException("Invalid value (" + + realVal + ") for parameter " + id + ".", + ex); + } catch (InvocationTargetException ex) { + throw new InitialisationException("Invalid value (" + + realVal + ") for parameter " + id + ".", + ex); + + } catch (IllegalArgumentException ex) { + throw new InitialisationException("Invalid value (" + + realVal + ") for parameter " + id + ".", + ex); + } + } + + private static Object getTypedParamValue(Element paramElt) throws InitialisationException { + String paramType = paramElt.getAttribute("type"); + if (paramType == "") { + throw new InitialisationException("<param> element must have a type"); + } + // for most params the actual value is in the text + String textVal = paramElt.getTextContent(); + // convert it + Object ans = null; + try { + if (paramType.equals("integer")) { + ans = Integer.parseInt(textVal.trim()); + } else if (paramType.equals("number")) { + ans = Double.parseDouble(textVal.trim()); + } else if (paramType.equals("listString")) { + String[] slist = textVal.trim().split(","); + for (int i = 0; i < slist.length; i++) { + slist[i] = slist[i].trim(); + } + ans = slist; + } else if (paramType.equals("listInteger")) { + String[] slist = textVal.trim().split(","); + int[] ilist = new int[slist.length]; + for (int i = 0; i < slist.length; i++) { + ilist[i] = Integer.parseInt(slist[i].trim()); + } + ans = ilist; + } else if (paramType.equals("listNumber") || paramType.equals("range")) { + String[] slist = textVal.trim().split(","); + if (paramType.equals("range") && slist.length != 2) { + throw new InitialisationException("A range must have 2 elements."); + } + double[] dlist = new double[slist.length]; + for (int i = 0; i < slist.length; i++) { + dlist[i] = Double.parseDouble(slist[i].trim()); + } + ans = dlist; + } else if (paramType.equals("paymentPattern")) { + PaymentPattern.Incidence inc = PaymentPattern.Incidence.EVEN; + double[] dlist = null; + NodeList kids = paramElt.getChildNodes(); + for (int j =0; j < kids.getLength(); j++) { + if (kids.item(j).getNodeType() != Node.ELEMENT_NODE) { + continue; // skip this one + } + Element kid = (Element) kids.item(j); + if (kid.getTagName().equals("incidence")) { + String iString = kid.getTextContent().trim(); + if (iString.equalsIgnoreCase("EVEN")) { + inc = PaymentPattern.Incidence.EVEN; + } else if (iString.equalsIgnoreCase("FRONT")) { + inc = PaymentPattern.Incidence.FRONT; + } else if (iString.equalsIgnoreCase("OTHER")) { + inc = PaymentPattern.Incidence.OTHER; + } else { + throw new InitialisationException("Unrecognised incidence type: " + iString); + } + } else if (kid.getTagName().equals("values")) { + // the value is a list of doubles + String[] slist = kid.getTextContent().trim().split(","); + dlist = new double[slist.length]; + for (int i = 0; i < slist.length; i++) { + dlist[i] = Double.parseDouble(slist[i].trim()); + } + } + } + if (dlist == null) { + throw new InitialisationException("Missing values in PaymentPattern " + + paramElt.getAttribute("id")); + } + ans = new PaymentPattern(inc, dlist); + + } else { + throw new InitialisationException("Unrecognised parameter type: " + paramType); + } + } catch (NumberFormatException ex) { + throw new InitialisationException("Invalid parameter value: " + textVal, ex); + } + return ans; + } + + private static boolean nodeHasOneChild(Node n) { + NodeList kids = n.getChildNodes(); + return (kids.getLength() == 1); + } } Index: BusinessLine.java =================================================================== RCS file: /cvsroot/icamodel/icamodel/src/icamodel/framework/BusinessLine.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** BusinessLine.java 24 Mar 2007 19:33:30 -0000 1.2 --- BusinessLine.java 24 Jun 2007 16:09:35 -0000 1.3 *************** *** 68,73 **** * Each represents proportion of contracts incepting in time period from start of projection. */ ! public void setInceptionPattern(PaymentPattern.Incidence incidence, double... args) { ! inceptionPattern = new PaymentPattern(incidence, args); writingDelayPattern = new PaymentPattern(PaymentPattern.Incidence.FRONT, 1.0); writingPattern = PaymentPattern.compoundPatterns(inceptionPattern, writingDelayPattern); --- 68,73 ---- * Each represents proportion of contracts incepting in time period from start of projection. */ ! public void setInceptionPattern(PaymentPattern pattern) { ! inceptionPattern = pattern; writingDelayPattern = new PaymentPattern(PaymentPattern.Incidence.FRONT, 1.0); writingPattern = PaymentPattern.compoundPatterns(inceptionPattern, writingDelayPattern); *************** *** 81,86 **** * Each element represents proportion of each contract's risk exposure in time period from inception. */ ! public void setExposureDelayPattern(PaymentPattern.Incidence incidence, double... args) { ! exposureDelayPattern = new PaymentPattern(incidence, args); exposurePattern = PaymentPattern.compoundPatterns(inceptionPattern, exposureDelayPattern); earningDelayPattern = new PaymentPattern(exposureDelayPattern); --- 81,86 ---- * Each element represents proportion of each contract's risk exposure in time period from inception. */ ! public void setExposureDelayPattern(PaymentPattern pattern) { ! exposureDelayPattern = pattern; exposurePattern = PaymentPattern.compoundPatterns(inceptionPattern, exposureDelayPattern); earningDelayPattern = new PaymentPattern(exposureDelayPattern); *************** *** 94,99 **** * Each represents proportion of each contract's premiums received in time period from inception. */ ! public void setPremiumReceiptDelayPattern(PaymentPattern.Incidence incidence, double... args) { ! receiptDelayPattern = new PaymentPattern(incidence, args); receiptPattern = PaymentPattern.compoundPatterns(inceptionPattern, receiptDelayPattern); } --- 94,99 ---- * Each represents proportion of each contract's premiums received in time period from inception. */ ! public void setPremiumReceiptDelayPattern(PaymentPattern pattern) { ! receiptDelayPattern = pattern; receiptPattern = PaymentPattern.compoundPatterns(inceptionPattern, receiptDelayPattern); } |