package WebGUI::JSONCollateral; =head1 LEGAL ------------------------------------------------------------------- WebGUI is Copyright 2001-2009 Plain Black Corporation. ------------------------------------------------------------------- Please read the legal notices (docs/legal.txt) and the license (docs/license.txt) that came with this distribution before using this software. ------------------------------------------------------------------- http://www.plainblack.com info@plainblack.com ------------------------------------------------------------------- =cut use strict; use Class::C3; =head1 NAME Package WebGUI::JSONCollateral =head1 DESCRIPTION This is an aspect which allows you to use JSON in the database transparently. =head1 SYNOPSIS use Class::C3; use base qw(WebGUI::JSONCollateral); $self->setJSONCollateral(); $self->getJSONCollateral(); $self->moveJSONCollateralUp(); $self->moveJSONCollateralDown(); And then wherever you would call $self->SUPER::someMethodName call $self->next::method instead. Classes that use this Aspect must have an update method that transparently serializes and deserializes data to and from JSON into perl data structures. See WebGUI::Crud->update, and Asset->update for examples. =head1 METHODS These methods are available from this class: =cut #------------------------------------------------------------------- =head2 deleteJSONCollateral ( fieldName, keyName, keyValue ) Deletes a row of collateral data. Returns false if the requested collateral was not deleted. =head3 fieldName The name of the field you wish to delete the data from. =head3 keyName The name of a key in the collateral hash. Typically a unique identifier for a given "row" of collateral data. =head3 keyValue Along with keyName, determines which "row" of collateral data to delete. =cut sub deleteJSONCollateral { my $self = shift; my $fieldName = shift; my $keyName = shift; my $keyValue = shift; my $field = $self->get($fieldName); my $index = $self->getJSONCollateralDataIndex($field, $keyName, $keyValue); return if $index == -1; splice @{ $field }, $index, 1; $self->update({ $fieldName => $field }); return 1; } #------------------------------------------------------------------- =head2 getJSONCollateral ( fieldName, keyName, keyValue ) Returns a hash reference containing one row of collateral data from a particular field. =head3 fieldName The name of the field you wish to retrieve the data from. =head3 keyName The name of a key in the collateral hash. Typically a unique identifier for a given "row" of collateral data. =head3 keyValue Along with keyName, determines which "row" of collateral data to get. If this is equal to "new", then an empty hashRef will be returned to avoid strict errors in the caller. If the requested data does not exist in the collateral array, it also returns an empty hashRef. =cut sub getJSONCollateral { my $self = shift; my $fieldName = shift; my $keyName = shift; my $keyValue = shift; if ($keyValue eq "new" || $keyValue eq "") { return {} } my $field = $self->get($fieldName); my $index = $self->getJSONCollateralDataIndex($field, $keyName, $keyValue); return {} if $index == -1; my %copy = %{ $field->[$index] }; return \%copy; } #------------------------------------------------------------------- =head2 getJSONCollateralDataIndex ( field, keyName, keyValue ) Returns the index in a set of collateral where an element of the data (keyName) has a certain value (keyValue). If the criteria are not found, returns -1. =head3 field The collateral data to search =head3 keyName The name of a key in the collateral hash. =head3 keyValue The value that keyName should have to meet the criteria. =cut sub getJSONCollateralDataIndex { my $self = shift; my $field = shift; my $keyName = shift; my $keyValue = shift; for (my $index=0; $index <= $#{ $field }; $index++) { return $index if (exists($field->[$index]->{$keyName}) && ($field->[$index]->{$keyName} eq $keyValue )); } return -1; } #------------------------------------------------------------------- =head2 moveJSONCollateralDown ( fieldName, keyName, keyValue ) Moves a collateral data item down one position, toward the end of the array where the indices are the highest, swapping the referenced piece of collateral (index) with the collateral just above it (index+1). For the list of collateral 1,2,3, if called on 2 the resultig list will be 1,3,2. If called on the last element of the collateral array then it does nothing. Returns 1 if the move is successful. Returns undef or the empty array otherwise. =head3 fieldName A string indicating the field that contains the collateral data. =head3 keyName The name of a key in the collateral hash. Typically a unique identifier for a given "row" of collateral data. =head3 keyValue Along with keyName, determines which "row" of collateral data to move. =cut sub moveJSONCollateralDown { my $self = shift; my $fieldName = shift; my $keyName = shift; my $keyValue = shift; my $field = $self->get($fieldName); my $index = $self->getJSONCollateralDataIndex($field, $keyName, $keyValue); return if $index == -1; return unless (abs($index) < $#{$field}); @{ $field }[$index,$index+1] = @{ $field }[$index+1,$index]; $self->update({ $fieldName => $field }); return 1; } #------------------------------------------------------------------- =head2 moveJSONCollateralUp ( fieldName, keyName, keyValue ) Moves a collateral data item "up" one position, toward the end of the array where the indices are the lowest, swapping the referenced piece of collateral (index) with the collateral just below it (index-1). For the list of collateral 1,2,3, if called on 2 the resultig list will be 2,1,3. If called on the first element of the collateral array then it does nothing. Returns 1 if the move is successful. Returns undef or the empty array otherwise. =head3 fieldName A string indicating the field that contains the collateral data. =head3 keyName The name of a key in the collateral hash. Typically a unique identifier for a given "row" of collateral data. =head3 keyValue Along with keyName, determines which "row" of collateral data to move. =cut sub moveJSONCollateralUp { my $self = shift; my $fieldName = shift; my $keyName = shift; my $keyValue = shift; my $field = $self->get($fieldName); my $index = $self->getJSONCollateralDataIndex($field, $keyName, $keyValue); return unless $index > 0; #-1 means that it could not be found, and we cannot move index 0 @{ $field }[$index-1,$index] = @{ $field }[$index,$index-1]; $self->update({ $fieldName => $field }); return 1; } #----------------------------------------------------------------- =head2 setJSONCollateral ( fieldName, keyName, keyValue, properties ) Performs and insert/update of collateral data for any wobject's collateral data. Returns the id of the data that was set, even if a new row was added to the data. =head3 fieldName The name of the field to insert the data. =head3 keyName The name of a key in the collateral hash. Typically a unique identifier for a given "row" of collateral data. =head3 keyValue Along with keyName, determines which "row" of collateral data to set. The index of the collateral data to set. If the keyValue = "new", then a new entry will be appended to the end of the collateral array. Otherwise, the appropriate entry will be overwritten with the new data. =head3 properties A hash reference containing the name/value pairs to be inserted into the collateral, using the criteria mentioned above. =cut sub setJSONCollateral { my $self = shift; my $fieldName = shift; my $keyName = shift; my $keyValue = shift; my $properties = shift; ##Note, since this returns a reference, it is actually updating ##the object cache directly. my $field = $self->get($fieldName); if ($keyValue eq 'new' || $keyValue eq '') { if ( ! exists $properties->{$keyName} or ! $self->session->id->valid($properties->{$keyName})) { $properties->{$keyName} = $self->session->id->generate; } push @{ $field }, $properties; $self->update({$fieldName => $field}); return $properties->{$keyName}; } my $index = $self->getJSONCollateralDataIndex($field, $keyName, $keyValue); return if $index == -1; $field->[$index] = $properties; $self->update({ $fieldName => $field }); return $keyValue; } 1;