![]()
Note
Assumes you created the project with bocca create
project demo --language=java.
Edit the evaluate method in the implementation file (also known as ``the impl'') that Bocca has generated for you (by invoking Babel ). Use the bocca edit -i to go directly to each method.
$
bocca edit -i Function evaluate
The editor opens up in the place where the implementation code for evaluate must be put. You see a default implementation generated by Babel for all user methods: the throwing of an exception which says the method is not yet implemented.
public double evaluate_Impl (
/*in*/ double x )
throws sidl.RuntimeException.Wrapper
{
// DO-NOT-DELETE splicer.begin(demo.Function.evaluate)
// Insert-Code-Here {demo.Function.evaluate} (evaluate)
/*
* This method has not been implemented
*/
// DO-DELETE-WHEN-IMPLEMENTING exception.begin(demo.Function.evaluate)
sidl.NotImplementedException noImpl = new sidl.NotImplementedException();
noImpl.setNote("This method has not been implmented.");
sidl.RuntimeException.Wrapper rex = (sidl.RuntimeException.Wrapper) sidl.RuntimeException.Wrapper._cast(noImpl);
throw rex;
// DO-DELETE-WHEN-IMPLEMENTING exception.end(demo.Function.evaluate)
// DO-NOT-DELETE splicer.end(demo.Function.evaluate)
As the comment suggests, this method is ``not implemented'', but some
code has been inserted by Babel to make sure an exception is thrown
to inform the user if this method is called by mistake. Delete this
exception code and substitute an implementation for the
PiFunction (i.e., the integral from 0 to 1 of
4/(1 + x2)
is an approximation of
).
// DO-NOT-DELETE splicer.begin(demo.Function.evaluate)
return 4.0 / (1.0 + x * x);
// DO-NOT-DELETE splicer.end(demo.Function.evaluate)
Now in the same file just above the evaluate method, find the second method for the FunctionPort init method:
// DO-NOT-DELETE splicer.begin(demo.Function.init)
// Do nothing.
// DO-NOT-DELETE splicer.end(demo.Function.init)
We don't have any initialization in this simple example, so we just eliminate the code that throws the exception when the method is executed.
After quitting the editor the state of the source code tree is updated if there are any dependencies on the edited implementation. Usually there are no dependencies on the implementation file, so Bocca does very little after you exit the editor and all you see is the information from the edit command about what file was edited:
/home/bernhold/bassi/project/projectdirs/cca/pde-hands-on/doc/scratch/java/demo/components/demo.Function/demo/Function_Impl.java
Similarly edit the march method in the Integrator with
$
bocca edit -i Integrator march
public double march_Impl (
/*in*/ double lowBound,
/*in*/ double upBound,
/*in*/ int count )
throws sidl.RuntimeException.Wrapper
{
// DO-NOT-DELETE splicer.begin(demo.Integrator.march)
// Insert-Code-Here {demo.Integrator.march} (march)
/*
* This method has not been implemented
*/
// DO-DELETE-WHEN-IMPLEMENTING exception.begin(demo.Integrator.march)
sidl.NotImplementedException noImpl = new sidl.NotImplementedException();
noImpl.setNote("This method has not been implmented.");
sidl.RuntimeException.Wrapper rex = (sidl.RuntimeException.Wrapper) sidl.RuntimeException.Wrapper._cast(noImpl);
throw rex;
// DO-DELETE-WHEN-IMPLEMENTING exception.end(demo.Integrator.march)
// DO-NOT-DELETE splicer.end(demo.Integrator.march)
Again remove this boilerplate exception code and insert an implementation of the Trapezoid rule for integration that uses the FunctionPort :
// DO-NOT-DELETE splicer.begin(demo.Integrator.march)
gov.cca.Port port = null;
port = this.d_services.getPort("odeRHS");
demo.FunctionPort odeRHS;
odeRHS = ( demo.FunctionPort.Wrapper )
demo.FunctionPort.Wrapper._cast((gov.cca.Port.Wrapper)port);
if (odeRHS == null) {
if (bocca_print_errs) {
System.err.println("demo.Integrator: Error casting gov.cca.Port"
+ " odeRHS to type demo.FunctionPort");
}
sidl.SIDLException ex = new sidl.SIDLException();
sidl.SIDLException.Wrapper msg = (sidl.SIDLException.Wrapper)
sidl.SIDLException.Wrapper._cast(ex);
throw msg;
}
double h = (upBound - lowBound) / count;
double retval = 0.0;
double sum = 0.0;
for (int i = 1; i <= count; i++){
sum += odeRHS.evaluate(lowBound + (i - 1) * h) +
odeRHS.evaluate(lowBound + i * h);
}
retval = h/2.0 * sum;
this.d_services.releasePort("odeRHS");
return retval;
// DO-NOT-DELETE splicer.end(demo.Integrator.march)
After quitting the editor the state of the source code tree is updated if there are any dependencies on the edited implementation. Usually there are no dependencies on the implementation file, so Bocca does very little after you exit the editor and all you see is the information from the edit command about what file was edited:
/home/bernhold/bassi/project/projectdirs/cca/pde-hands-on/doc/scratch/java/demo/components/demo.Integrator/demo/Integrator_Impl.java
Finally for the Driver component we have to implement the GoPort details to get things going. Bocca will take you to the generated method, which looks like this:
$
bocca edit -i Driver go
public int go_Impl ()
throws sidl.RuntimeException.Wrapper
{
// DO-NOT-DELETE splicer.begin(demo.Driver.go)
// Bocca generated code. bocca.protected.begin(demo.Driver.go:boccaGoProlog)
int bocca_status = 0;
// The user's code should set bocca_status 0 if computation proceeded ok.
// The user's code should set bocca_status -1 if computation failed but might
// succeed on another call to go(), e.g. wheh a required port is not yet connected.
// The user's code should set bocca_status -2 if the computation failed and can
// never succeed in a future call.
// The users's code should NOT use return in this function;
// Exceptions that are not caught in user code will be converted to status 2.
gov.cca.Port port = null;
boolean integrate_fetched = false;
if (bocca_status == 0) { // skip further getports if problem occurs.
// Use a demo.Integration port with port name integrate, unless we've hit
// a problem already.
try{
port = this.d_services.getPort("integrate");
} catch ( gov.cca.CCAException.Wrapper ex ) {
// we will continue with port nil (never successfully assigned) and set a flag.
if (bocca_print_errs) {
System.err.println("Error calling getPort(\"integrate\")"
+ ex.getNote());
System.err.println("Continuing without integrate");
}
}
demo.Integration integrate;
if ( port != null ) {
integrate_fetched = true; // even if the next cast fails, must release.
integrate = ( demo.Integration.Wrapper )
demo.Integration.Wrapper._cast((gov.cca.Port.Wrapper)port);
if (integrate == null) {
if (bocca_print_errs) {
System.err.println("demo.Driver: Error casting gov.cca.Port "
+ "integrate to type demo.Integration");
}
bocca_status = -1;
}
}
}
if (bocca_status == 0) {
// skip user code if we already have an unexpected error. go to cleanup.
// Bocca generated code. bocca.protected.end(demo.Driver.go:boccaGoProlog)
// If this try/catch block is rewritten by the user, we will not change it.
try {
// All port instances may be rechecked for null before calling in user code.
// Java will throw a null object exception when using the port if it's null.
// The port instance names used in registerUsesPort appear as local variable
// names here.
// Insert-UserCode-Here {demo.Driver.go}
// BEGIN REMOVE ME BLOCK
sidl.SIDLException ex = new sidl.SIDLException();
ex.setNote("USER FORGOT TO FILL IN THEIR FUNCTION demo.Driver.go()");
sidl.BaseException.Wrapper bex =
(sidl.BaseException.Wrapper)sidl.BaseException.Wrapper._cast(ex);
throw bex;
// END REMOVE ME BLOCK
} catch (sidl.BaseException.Wrapper ex) {
bocca_status = -2;
if (bocca_print_errs) {
System.err.println("SIDL Exception in user go code: "+ ex.getNote() );
System.err.println("Returning 2 from go()");
}
} catch (java.lang.Exception jex) {
bocca_status = -2;
if (bocca_print_errs) {
if (((sidl.BaseInterface)jex).isType("sidl.BaseException")) {
System.err.println("sidl Exception in user go code: "
+ ((sidl.BaseException)jex).getNote() );
} else {
System.err.println("java Exception in user go code: "+ jex.getMessage());
}
System.err.println("Returning 2 from go()");
}
// If unknown exceptions in the user code are tolerable and restart is ok,
// use bocca_status -1 instead.
// 2 means the component is so confused that it and probably the application
// should be destroyed.
}
// Bocca generated code. bocca.protected.begin(demo.Driver.go:boccaGoEpilog)
} // cleanup
// release integrate
if (integrate_fetched) {
integrate_fetched = false;
try{
this.d_services.releasePort("integrate");
} catch ( gov.cca.CCAException.Wrapper ex ) {
if (bocca_print_errs) {
System.err.println("demo.Driver: Error calling "
+ "releasePort(\"integrate\"): " + ex.getNote());
}
}
// java port reference will be dropped when function exits,
// but we must tell framework.
}
return bocca_status;
// Bocca generated code. bocca.protected.end(demo.Driver.go:boccaGoEpilog)
/*
* This method has not been implemented
*/
// DO-NOT-DELETE splicer.end(demo.Driver.go)
Find the REMOVE block within the go method implementation, delete it, and insert the numerical logic needed to use the integrator.IntegratorPort port. Any required local variables should be inserted just before the boccaGoProlog protected block.
The go subroutine will be called by the framework when the component's run button (the name of this particular GoPort instance) is pushed in the GUI. Bocca generates the code to the Integration that the Driver is connected to. We just have to use it to compute the integral and return the proper value for bocca_status.
// DO-NOT-DELETE splicer.begin(demo.Driver.go)
// Bocca generated code. bocca.protected.begin(demo.Driver.go:boccaGoProlog)
int bocca_status = 0;
// The user's code should set bocca_status 0 if computation proceeded ok.
// The user's code should set bocca_status -1 if computation failed but might
// succeed on another call to go(), e.g. wheh a required port is not yet connected.
// The user's code should set bocca_status -2 if the computation failed and can
// never succeed in a future call.
// The users's code should NOT use return in this function;
// Exceptions that are not caught in user code will be converted to status 2.
gov.cca.Port port = null;
boolean integrate_fetched = false;
if (bocca_status == 0) { // skip further getports if problem occurs.
// Use a demo.Integration port with port name integrate, unless we've hit
// a problem already.
try{
port = this.d_services.getPort("integrate");
} catch ( gov.cca.CCAException.Wrapper ex ) {
// we will continue with port nil (never successfully assigned) and set a flag.
if (bocca_print_errs) {
System.err.println("Error calling getPort(\"integrate\")"
+ ex.getNote());
System.err.println("Continuing without integrate");
}
}
demo.Integration integrate;
if ( port != null ) {
integrate_fetched = true; // even if the next cast fails, must release.
integrate = ( demo.Integration.Wrapper )
demo.Integration.Wrapper._cast((gov.cca.Port.Wrapper)port);
if (integrate == null) {
if (bocca_print_errs) {
System.err.println("demo.Driver: Error casting gov.cca.Port "
+ "integrate to type demo.Integration");
}
bocca_status = -1;
}
}
}
if (bocca_status == 0) {
// skip user code if we already have an unexpected error. go to cleanup.
// Bocca generated code. bocca.protected.end(demo.Driver.go:boccaGoProlog)
// If this try/catch block is rewritten by the user, we will not change it.
try {
// All port instances may be rechecked for null before calling in user code.
// Java will throw a null object exception when using the port if it's null.
// The port instance names used in registerUsesPort appear as local variable
// names here.
double value;
int count = 100000;
double lowerBound = 0.0, upperBound = 1.0;
// operate on the port
value = integrate.march(lowerBound, upperBound, count);
System.out.println("Value = "+ value);
} catch (sidl.BaseException.Wrapper ex) {
bocca_status = -2;
if (bocca_print_errs) {
System.err.println("SIDL Exception in user go code: "+ ex.getNote() );
System.err.println("Returning 2 from go()");
}
} catch (java.lang.Exception jex) {
bocca_status = -2;
if (bocca_print_errs) {
if (((sidl.BaseInterface)jex).isType("sidl.BaseException")) {
System.err.println("sidl Exception in user go code: "
+ ((sidl.BaseException)jex).getNote() );
} else {
System.err.println("java Exception in user go code: " + jex.getMessage() );
}
System.err.println("Returning 2 from go()");
}
// If unknown exceptions in the user code are tolerable and restart is ok,
// use bocca_status -1 instead.
// 2 means the component is so confused that it and probably the application
// should be destroyed.
}
// Bocca generated code. bocca.protected.begin(demo.Driver.go:boccaGoEpilog)
} // cleanup
// release integrate
if (integrate_fetched) {
integrate_fetched = false;
try{
this.d_services.releasePort("integrate");
} catch ( gov.cca.CCAException.Wrapper ex ) {
if (bocca_print_errs) {
System.err.println("demo.Driver: Error calling "
+ "releasePort(\"integrate\"): " + ex.getNote());
}
}
// java port reference will be dropped when function exits,
// but we must tell framework.
}
return bocca_status;
// Bocca generated code. bocca.protected.end(demo.Driver.go:boccaGoEpilog)
// DO-NOT-DELETE splicer.end(demo.Driver.go)
After quitting the editor the state of the source code tree is updated if there are any dependencies on the edited implementation. Usually there are no dependencies on the implementation file, so Bocca does very little after you exit the editor and all you see is the information from the edit command about what file was edited.
/home/bernhold/bassi/project/projectdirs/cca/pde-hands-on/doc/scratch/java/demo/components/demo.Driver/demo/Driver_Impl.java
Now remake your project tree to finish the components:
$
make
make[1]: Entering directory `/home/bernhold/bassi/project/projectdirs/cca/pde-hands-on/doc/scratch/java/demo' # ======================================================================= # No SIDL files in external/sidl, skipping build for external # ======================================================================= # ======================================================================= # Building in ports/, languages: # ======================================================================= ## Building ports... # ======================================================================= # Building in components/clients/, languages: # ======================================================================= ## Building clients... # ======================================================================= # Building in components/, languages: # ======================================================================= [s] Building class/component demo.Driver: ### Warning: demo.Driver build disabled since java is not supported by the current project configuration. ### Warning: demo.Driver build disabled since java is not supported by the current project configuration. [s] Building class/component demo.Function: ### Warning: demo.Function build disabled since java is not supported by the current project configuration. ### Warning: demo.Function build disabled since java is not supported by the current project configuration. [s] Building class/component demo.Integrator: ### Warning: demo.Integrator build disabled since java is not supported by the current project configuration. ### Warning: demo.Integrator build disabled since java is not supported by the current project configuration. [s] Building class/component demo.emptyComponent: ### Warning: demo.emptyComponent build disabled since java is not supported by the current project configuration. ### Warning: demo.emptyComponent build disabled since java is not supported by the current project configuration. ################ Finished building everything ################# ####### You can run some simple tests with 'make check' ####### make[1]: Leaving directory `/home/bernhold/bassi/project/projectdirs/cca/pde-hands-on/doc/scratch/java/demo'
It is good practice to do a make check at this point:
$
make check
make[1]: Entering directory `/home/bernhold/bassi/project/projectdirs/cca/pde-hands-on/doc/scratch/java/demo' make --no-print-directory --no-builtin-rules -C components check ### Test library load and instantiation for the following languages: java No CCA components to test for instantiation. make --no-print-directory --no-builtin-rules check-user make[1]: Leaving directory `/home/bernhold/bassi/project/projectdirs/cca/pde-hands-on/doc/scratch/java/demo'
You should now be able to instantiate these components, assemble them into an application, and run the application, following the same procedures as in Section 2, and get a result that's reasonably close to pi .
David E. Bernholdt [bek] 574-3147 2009-08-21