Error in Include(/www/htdocs/nge/dispatcher.html):
Required data was not found.
	primary_key => undef
	criteria => lower(regexp_replace(description, '[^a-zA-Z]', '', 'g')) = ?
 at /www/lib/perl/OmniTI/Class/TableBacked.pm line 1399

[    1]    1: =head1 NAME
[    2]    2: 
[    3]    3: OmniTI::Exception - OO Exceptions
[    4]    4: 
[    5]    5: =head1 SYNOPSIS
[    6]    6: 
[    7]    7:   use OmniTI::Exception;
[    8]    8: 
[    9]    9:   # In API code:
[   10]   10: 
[   11]   11:   # dies locally
[   12]   12:   OmniTI::Exception::Params::Missing->throw(param => 'id');
[   13]   13: 
[   14]   14:   # dies from caller's perspective
[   15]   15:   OmniTI::Exception::Params::Missing->croak(param => 'id');
[   16]   16: 
[   17]   17:   # dies from caller's caller's perspective
[   18]   18:   OmniTI::Exception::Params::Missing->croak(param => 'id', frames => 2);
[   19]   19: 
[   20]   20:   # To catch:
[   21]   21:   eval { something_dangerous(); }
[   22]   22:   if (my $e = OmniTI::Exception::Params::Missing->caught()) {
[   23]   23:     my $p = $e->param(); # Find out what was missing
[   24]   24:     print $e; #  Stringifies nicely
[   25]   25:   } else {
[   26]   26:     die $@; # Pass on unrecognized exceptions
[   27]   27:   }
[   28]   28: 
[   29]   29:   # Special handler included for working with OmniTI::DB connections....
[   30]   30:   my $dbh = NatGeo::DB::Magazine->new();
[   31]   31:   $dbh->set_handle_error(OmniTI::Exception->make_db_error_handler());
[   32]   32: 
[   33]   33: 
[   34]   34: =head1 DESCRIPTION
[   35]   35: 
[   36]   36: Uses Exception::Class to define a wide variety of exceptions.
[   37]   37: 
[   38]   38: =head1 STRINGIFICATION
[   39]   39: 
[   40]   40: Any extra fields defined for a particular exception 
[   41]   41: class will be included in the stringification of 
[   42]   42: the exception, like this:
[   43]   43: 
[   44]   44:   Error message
[   45]   45:      field1 => value1
[   46]   46:      field2 => value2
[   47]   47: 
[   48]   48: =head1 EXCEPTIONS
[   49]   49: 
[   50]   50: =over
[   51]   51: 
[   52]   52: =item OmniTI::Exception::Param
[   53]   53: 
[   54]   54: Exceptions related to parameter passing.  Expect fields 'param'.
[   55]   55: 
[   56]   56: =over
[   57]   57: 
[   58]   58: =item OmniTI::Exception::Param::Missing
[   59]   59: 
[   60]   60: =item OmniTI::Exception::Param::Empty
[   61]   61: 
[   62]   62: An array or hash ref turned out to be present but empty.
[   63]   63: 
[   64]   64: =item OmniTI::Exception::Param::ExpectedHash
[   65]   65: 
[   66]   66: Thrown when the method uses named parameters, but an odd number of parameters were provided.  param field is not used.
[   67]   67: 
[   68]   68: =item OmniTI::Exception::Param::ExpectedHashRef
[   69]   69: 
[   70]   70: =item OmniTI::Exception::Param::ExpectedArrayRef
[   71]   71: 
[   72]   72: =item OmniTI::Exception::Param::ExpectedHashref
[   73]   73: 
[   74]   74: =item OmniTI::Exception::Param::MutuallyExclusive
[   75]   75: 
[   76]   76: Used when two parameters cannot both be present.  Use fields 'param' and 'other_param'.
[   77]   77: 
[   78]   78: =item OmniTI::Exception::Param::Duplicate
[   79]   79: 
[   80]   80: Thrown when the same named parameter is used more than once.
[   81]   81: 
[   82]   82: =back
[   83]   83: 
[   84]   84: =back
[   85]   85: 
[   86]   86: 
[   87]   87: =head1 AUTHOR
[   88]   88: 
[   89]   89:   Clinton Wolfe
[   90]   90: 
[   91]   91: =cut
[   92]   92: 
[   93]   93: package OmniTI::Exception;
[   94]   94: use strict;
[   95]   95: our $DEBUG = 0;
[   96]   96: use Data::Dumper;
[   97]   97: 
[   98]   98: 
[   99]   99: our @ISA = ('Exception::Class::Base');
[  100]  100: 
[  101]  101: sub full_message {
[  102]  102:     my $self = shift;
[  103]  103:     my @field_names = $self->Fields();
[  104]  104:     my $msg = $self->message . "\n"; # Automatic newline?
[  105]  105:     $msg .= ($self->description . "\n") || '';
[  106]  106:     foreach my $field (@field_names) {
[  107]  107:         my $val = $self->$field;
[  108]  108:         $msg .= "\t$field => " . (defined($val) ? $val : 'undef') . "\n";
[  109]  109:     }
[  110]  110: 
[  111]  111:     # Include filename and file
[  112]  112:     #print STDERR "In full_message, have frame count " . $self->trace->frame_count . "\n";
[  113]  113:     my $frame = $self->trace->frame(0);
[  114]  114:     $msg .= " at " . $frame->filename . " line " . $frame->line . "\n";
[  115]  115: 
[  116]  116:     return $msg;
[  117]  117: }
[  118]  118: 
[  119]  119: sub croak {
[  120]  120:     my $class = shift;
[  121]  121:     my %args;
[  122]  122: 
[  123]  123:     # Behave like throw: if one arg, it's the message.
[  124]  124:     if (@_ == 1) {
[  125]  125:         %args = (message => shift());
[  126]  126:     } else {
[  127]  127:         %args = @_;
[  128]  128:     }
[  129]  129: 
[  130]  130:     my $frame_count = defined($args{frames}) ? $args{frames} : 1;
[  131]  131:     delete $args{frames};
[  132]  132: 
[  133]  133:     my $self = $class->new(%args);
[  134]  134: 
[  135]  135:     my @frames  = @{$self->{trace}->{frames}};
[  136]  136:     #print STDERR "In croak, have orginal frame count " . (scalar @frames) . "\n";
[  137]  137:     my @dropped_frames = splice @frames, 0, $frame_count; # Delete $frame_count frames from the top (nearest) end of the stack.
[  138]  138:     $self->{trace}->{frames} = \@frames;
[  139]  139:     #print STDERR "In croak, have final frame count " . (scalar @frames) . "\n";
[  140]  140: 
[  141]  141:     if ($DEBUG > 1) {
[  142]  142:         print STDERR __PACKAGE__ . ':' . __FILE__ . " - Have dropped frames:\n";
[  143]  143:         for (@dropped_frames) {
[  144]  144:             print "\t" . $_->filename . ':' . $_->line . "\n";
[  145]  145:         }
[  146]  146:     }
[  147]  147: 
[* 148]  148:     die $self;
[  149]  149: }
[  150]  150: 
[  151]  151: # Returns a coderef suitable for setting the DBI HandleError attribute.
[  152]  152: sub make_db_error_handler {
[  153]  153:     my $class = shift;
[  154]  154:     my $code = sub {
[  155]  155:         my $errstr = shift;
[  156]  156:         my $dbh = shift;
[  157]  157:         my $bind_msg = '(in PREPARE stage)';
[  158]  158:         if ($dbh->{ParamValues}) {
[  159]  159:             my %binds = %{$dbh->{ParamValues}};
[  160]  160:             if ($DEBUG) { print STDERR __PACKAGE__ . ':' . __LINE__ . "In DB error handler, have binds:\n" .  Dumper(\%binds); }
[  161]  161:             $bind_msg = join ', ', map { $_ . ':' . (defined($binds{$_}) ? $binds{$_} : 'undef') } keys %binds;
[  162]  162:         }
[  163]  163:         OmniTI::Exception::Data::SqlError->croak(
[  164]  164:                                                  frames => 1,
[  165]  165:                                                  error => $errstr,
[  166]  166:                                                  statement => $dbh->{Statement},
[  167]  167:                                                  bind_values => $bind_msg,
[  168]  168:                                                 );
[  169]  169:     }
[  170]  170: }
[  171]  171: 
[  172]  172: 
[  173]  173: package main;
[  174]  174: 
[  175]  175: # Note: this should follow the definition of OmniTI::Exception
[  176]  176: use Exception::Class 
[  177]  177:   (
[  178]  178: 
[  179]  179:    # Coding
[  180]  180:    'OmniTI::Exception::NotImplemented' =>
[  181]  181:    {
[  182]  182:     isa => 'OmniTI::Exception',
[  183]  183:     description => 'The code that is being attempted to execute has not yet been written.',
[  184]  184:    },
[  185]  185:    'OmniTI::Exception::CannotLoadClass' =>
[  186]  186:    {
[  187]  187:     isa => 'OmniTI::Exception',
[  188]  188:     description => 'The requested class cannot be loaded.',
[  189]  189:     fields => [qw(class)],
[  190]  190:    },
[  191]  191: 
[  192]  192: 
[  193]  193: 
[  194]  194:    # Param handling
[  195]  195:    'OmniTI::Exception::Param' => 
[  196]  196:    {
[  197]  197:     isa => 'OmniTI::Exception',
[  198]  198:     description => 'A general parameter error',
[  199]  199:     fields => [ qw(param value) ],
[  200]  200:    },
[  201]  201: 
[  202]  202:    'OmniTI::Exception::Param::Missing' => 
[  203]  203:    {
[  204]  204:     isa => 'OmniTI::Exception::Param',
[  205]  205:     description => 'A required parameter is missing. The required parameter is listed in the param field.',
[  206]  206:    },
[  207]  207: 
[  208]  208:    'OmniTI::Exception::Param::BadValue' => 
[  209]  209:    {
[  210]  210:     isa => 'OmniTI::Exception::Param',
[  211]  211:     description => 'A parameter has an invalid value.',
[  212]  212:    },
[  213]  213: 
[  214]  214:    'OmniTI::Exception::Param::ExpectedHash' => 
[  215]  215:    {
[  216]  216:     isa => 'OmniTI::Exception::Param',
[  217]  217:     description => 'The method or subroutine expected to be called with named paramters, but an odd number of parameters were passed.',
[  218]  218:    },
[  219]  219: 
[  220]  220:    'OmniTI::Exception::Param::ExpectedArrayRef' => 
[  221]  221:    {
[  222]  222:     isa => 'OmniTI::Exception::Param',
[  223]  223:     description => 'A parameter was expected to be an array ref, but was not.  The parameter is listed in the param field.',
[  224]  224:    },
[  225]  225: 
[  226]  226:    'OmniTI::Exception::Param::ExpectedHashRef' => 
[  227]  227:    {
[  228]  228:     isa => 'OmniTI::Exception::Param',
[  229]  229:     description => 'A parameter was expected to be an hash ref, but was not.  The parameter is listed in the param field.',
[  230]  230:    },
[  231]  231: 
[  232]  232:    'OmniTI::Exception::Param::WrongType' => 
[  233]  233:    {
[  234]  234:     isa => 'OmniTI::Exception::Param',
[  235]  235:     description => 'A parameter is of the wrong type. ',
[  236]  236:     fields => [ qw(param expected) ],
[  237]  237:    },
[  238]  238: 
[  239]  239:    'OmniTI::Exception::Param::MutuallyExclusive' => 
[  240]  240:    {
[  241]  241:     isa => 'OmniTI::Exception::Param',
[  242]  242:     description => 'You may only provide or or the other of a pair of parameters, but you provided both.  The parameters are listed in the param and other_param field.',
[  243]  243:     fields => [ qw(param other_param) ],
[  244]  244:    },
[  245]  245: 
[  246]  246:    'OmniTI::Exception::Param::Duplicate' =>
[  247]  247:    {
[  248]  248:     isa => 'OmniTI::Exception::Param',
[  249]  249:     description => 'You specified the same parameter more than once in a list, when unique values are required.',
[  250]  250:    },
[  251]  251:    'OmniTI::Exception::Param::Spurious' =>
[  252]  252:    {
[  253]  253:     isa => 'OmniTI::Exception::Param',
[  254]  254:     description => 'You provided extra, unrecognized parameters.',
[  255]  255:    },
[  256]  256: 
[  257]  257: 
[  258]  258: 
[  259]  259:    # Other function calling problems
[  260]  260:    'OmniTI::Exception::Call' => 
[  261]  261:    {
[  262]  262:     isa => 'OmniTI::Exception',
[  263]  263:     description => 'A general error in function/method calling style',
[  264]  264:    },
[  265]  265: 
[  266]  266:    'OmniTI::Exception::Call::NotMutator' => 
[  267]  267:    {
[  268]  268:     isa => 'OmniTI::Exception::Call',
[  269]  269:     description => 'You may not use this function to set a value.',
[  270]  270:     fields => [ qw(attribute) ],
[  271]  271:    },
[  272]  272: 
[  273]  273:    'OmniTI::Exception::Call::NotPermitted' => 
[  274]  274:    {
[  275]  275:     isa => 'OmniTI::Exception::Call',
[  276]  276:     description => 'You may not call this method.',
[  277]  277:    },
[  278]  278: 
[  279]  279:    'OmniTI::Exception::Call::Deprecated' => 
[  280]  280:    {
[  281]  281:     isa => 'OmniTI::Exception::Call',
[  282]  282:     description => 'You may not call this method, because it is no longer supported.',
[  283]  283:    },
[  284]  284: 
[  285]  285:    'OmniTI::Exception::Call::PureVirtual' => 
[  286]  286:    {
[  287]  287:     isa => 'OmniTI::Exception::Call',
[  288]  288:     description => 'This method may not be called directly, because a subclass is supposed to provide its own implementation.',
[  289]  289:    },
[  290]  290: 
[  291]  291:    'OmniTI::Exception::Call::NoSuchMethod' => 
[  292]  292:    {
[  293]  293:     isa => 'OmniTI::Exception::Call',
[  294]  294:     description => 'You tried to use a method that does not exist.  This usually means the module does not know how to AUTOLOAD the requested method.',
[  295]  295:    },
[  296]  296: 
[  297]  297: 
[  298]  298:    # Database problems
[  299]  299:    'OmniTI::Exception::Data' =>
[  300]  300:    {
[  301]  301:     isa => 'OmniTI::Exception',
[  302]  302:     description => 'A general data-related error.',
[  303]  303:     fields => [ qw(primary_key) ],
[  304]  304:    },
[  305]  305: 
[  306]  306:    'OmniTI::Exception::Data::NotFound' =>
[  307]  307:    {
[  308]  308:     isa => 'OmniTI::Exception::Data',
[  309]  309:     description => 'Required data was not found.',
[  310]  310:     fields => [ qw(criteria) ],
[  311]  311:    },
[  312]  312: 
[  313]  313:    'OmniTI::Exception::Data::AlreadyInserted' =>
[  314]  314:    {
[  315]  315:     isa => 'OmniTI::Exception::Data',
[  316]  316:     description => 'A data object is marked as already existing in the database, but you just tried to insert it again.',
[  317]  317:    },
[  318]  318:    'OmniTI::Exception::Data::DependsOnInsert' =>
[  319]  319:    {
[  320]  320:     isa => 'OmniTI::Exception::Data',
[  321]  321:     description => 'This object depends on another data object, which must be inserted before you can perform this operation.',
[  322]  322:    },
[  323]  323: 
[  324]  324:    'OmniTI::Exception::Data::UpdateWithoutInsert' =>
[  325]  325:    {
[  326]  326:     isa => 'OmniTI::Exception::Data',
[  327]  327:     description => 'A data object is marked as not yet existing in the database, but you just tried to do an UPDATE on it.',
[  328]  328:    },
[  329]  329: 
[  330]  330:    'OmniTI::Exception::Data::DeleteWithoutInsert' =>
[  331]  331:    {
[  332]  332:     isa => 'OmniTI::Exception::Data',
[  333]  333:     description => 'A data object is marked as not yet existing in the database, but you just tried to do a DELETE on it.',
[  334]  334:    },
[  335]  335: 
[  336]  336:    'OmniTI::Exception::Data::NeedMoreKeys' =>
[  337]  337:    {
[  338]  338:     isa => 'OmniTI::Exception::Data',
[  339]  339:     description => 'An operation depends on having multiple primary or foreign keys, but you did not provide enough keys.',
[  340]  340:    },
[  341]  341: 
[  342]  342:    'OmniTI::Exception::Data::SqlError' =>
[  343]  343:    {
[  344]  344:     isa => 'OmniTI::Exception::Data',
[  345]  345:     description => 'An error occured within the database.',
[  346]  346:     fields => [ qw(statement bind_values) ],
[  347]  347:    },
[  348]  348: 
[  349]  349:    'OmniTI::Exception::Data::AmbiguousReference' =>
[  350]  350:    {
[  351]  351:     isa => 'OmniTI::Exception::Data',
[  352]  352:     description => 'A table or column reference could not be disambiguated.',
[  353]  353:     fields => [ qw(statement referent) ],
[  354]  354:    },
[  355]  355: 
[  356]  356:    'OmniTI::Exception::Data::UnsupportedCascade' =>
[  357]  357:    {
[  358]  358:     isa => 'OmniTI::Exception::Data',
[  359]  359:     description => 'An insert or update would require performing a cascading insert or update, which is not supported.',
[  360]  360:    },
[  361]  361: 
[  362]  362:    'OmniTI::Exception::Data::FetchRequired' =>
[  363]  363:    {
[  364]  364:     isa => 'OmniTI::Exception::Data',
[  365]  365:     description => 'You tried to access a child object using an ORM, but the child object has not been fetched yet.  Rather than make hidden DB calls, you should call fetch_METHOD.',
[  366]  366:     fields => [ qw(call_instead called) ],
[  367]  367:    },
[  368]  368: 
[  369]  369:    # TODO - add more exception classes as needed
[  370]  370: 
[  371]  371:   );
[  372]  372: 
[  373]  373: 
[  374]  374: 1;