text:
//
//  KMotionDef.h - MAIN HEADER FILE FOR USER C PROGRAMS
//
//  Copyright Dynomotion 2/20/2004
//
//  Include this header file in User C programs that execute
//  in the DSP to define all User accessible KMotion functions,
//  constants, and data structures

#ifndef KMotionDef_h
#define KMotionDef_h

#define KFLOP
#define C6722

#define BOARD "KFLOP"

extern const char VersionAndBuildTime[];  // string with version and build time

#define CLOCKFREQ   50.0e6   // 200 MHz/4

typedef int BOOL;

#ifndef _SIZE_T
#define _SIZE_T
typedef unsigned int size_t;
#endif

#ifndef NULL
#define NULL    0
#endif

#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef PI
#define PI 3.14159265358979323846264
#endif
#ifndef PI_F
#define PI_F 3.1415926535f
#endif
#ifndef TWO_PI_F
#define TWO_PI_F (2.0f * 3.1415926535f)
#endif
#ifndef PI_2F
#define PI_2F (3.1415926535f * 0.5f)
#endif
#ifndef TWO_PI
#define TWO_PI (2.0 * 3.14159265358979323846264)
#endif

#include "PC-DSP.h"   // contains common structures shared by PC and DSP

// Global Host Status that the PC Application can specify as it Requests Global Status
// to inform KFLOP User threads of its current state.  ie Job Actively running
// up to 32 bits of status can be specified.  See PC-DSP.h for normal bit defines
extern int volatile HostStatus;

#define JOB_ACTIVE (HostStatus & HOST_JOB_ACTIVE_BIT)

// standard math funtions

extern float sqrtf (float x);
extern float expf  (float x);
extern float logf  (float x);
extern float log10f(float x);
extern float powf  (float x, float y);
extern float sinf  (float x);
extern float cosf  (float x);
extern float tanf  (float x);
extern float asinf (float x);
extern float acosf (float x);
extern float atanf (float x);
extern float atan2f(float y, float x);
extern float fast_fabsf (float y);

extern double sqrt (double x);
extern double exp  (double x);
extern double log  (double x);
extern double log10(double x);
extern double pow  (double x, double y);
extern double sin  (double x);
extern double cos  (double x);
extern double tan  (double x);
extern double asin (double x);
extern double acos (double x);
extern double atan (double x);
extern double atan2(double y, double x);
extern double fast_fabs (double y);

#define FPGA_ADDR ((volatile unsigned char *)0x91000000)   // Base of FPGA addresses
#define FPGA(X) (FPGA_ADDR[(X)*4+2])
#define FPGA_ADDRW ((volatile unsigned short int *)0x91000000)   // Base of FPGA addresses
#define FPGAW(X) (FPGA_ADDRW[(X)*2+1])

// This structure is set to default every time the program runs UNTIL
// the program image has been FLASHED using the FLASH command
// from then on it will not be cleared, so data that was present at the
// time it was flashed will persist

#define N_USER_DATA_VARS 200

typedef struct
{
    int RunOnStartUp; // word Bits 1-7 selects which threads to execute on startup
    unsigned int EntryPoints[N_USER_THREADS];   // each downloaded program's entry point
    int UserData[N_USER_DATA_VARS]; // General purpose way to share and or save user program data
} PERSIST;

extern PERSIST persist;

extern int StatusRequestCounter;  // increments each time host requests status

// data gathering variables

#define MAX_GATHER_VALUES 32

#define GATHER_NULL_TYPE 7
#define GATHER_ADC_TYPE 6
#define GATHER_DOUBLE_TYPE 5
#define GATHER_FLOAT_TYPE 4
#define GATHER_LASTPWMC_TYPE 3
#define GATHER_LASTPWM_TYPE 2
#define GATHER_INT_TYPE 1
#define GATHER_END_TYPE 0

typedef struct  // define a size and address to store
{
    int type;    // GATHER_XXXXX_TYPE, 0=end of list
    void *addr;
} GATHER_VALUE_DEF;

typedef struct
{
    double *bufptr;         // data gathering buffer pointer
    double *endptr;         // done if bufptr = endptr

    double Dest;             // Save where the injection will be relative to

    int Inject;             // if set, 1st address is to be copied from buffer to the address

    GATHER_VALUE_DEF list[MAX_GATHER_VALUES];   // list of addresses to gather (null after last value)
} GATHER;

extern GATHER gather;

#define MAX_GATHER_DATA 1000000 // Size of gather buffer (number of doubles, 8 bytes each).
extern double *gather_buffer;   // Large buffer for data gathering, Bode plots, or User use

#define N_CPLX 2048

extern float *input;

void SetupGatherAllOnAxis(int c, int n_Samples);  // Prepares to gather info for an axis
void TriggerGather();                             // starts gathering defined items into gather buffer

#define TRAJECTORY_OFF 0          // no trajectory generation
#define TRAJECTORY_INDEPENDENT 1  // simple independent axis (3rd order funtion of time)
#define TRAJECTORY_LINEAR 2       // linear interpolated from coord system 0    (x = c*p+d)
#define TRAJECTORY_CIRCULAR 3     // circular interpolated from coord system 0  (x = c*sin(p*a+b)+d)
#define TRAJECTORY_SPECIAL 4      // Special Command to clear/set IO bit
								  // do the operation
								  // 0 = clearbit
								  // 1 = setbit
								  // 2 = wait for bit low
								  // 3 = wait for bit high
								  // 4 = beginning of Rapid
								  // 5 = end of Rapid

								  //    param 0 = bit number

#define TRAJECTORY_EXPONENTIAL 5  // independent axis (exponentially approach Dest a=Ratio per tick, b=Dest)

#define LAST_MOTION_JOG 0		  // type of last independent motion was a jog
#define LAST_MOTION_MOVE 1		  // type of last independent motion was a move
#define LAST_MOTION_MULTI 2		  // type of last independent motion was a multi axis move (G0 type)
#define LAST_MOTION_EXP 3		  // type of last independent motion was an exponential

typedef struct  // linear (only c and d are used),or sine equation
{
    double a;
    double b;
    double c;
    double d;   // always t^0 constant coefficient (starting position)
} TRIP_CIRCLE_LINEAR;

typedef struct  // linear (only c and d are used)
{
    double c;
    double d;   // always t^0 constant coefficient (starting position)
} TRIP_LINEAR;

//
// Motion structure for a coordinate system
//
// 3rd order polynomial for the parametric parameter
//
// defines a parametric parameter p that varies from 0->1 over the
// segment of motion as a function of time.  All the associated axes
// derive their position from this (either circular or linear)
// using either a circular formula or linear formula

typedef struct
{
    char trajectory_mode;    // Off, circular, or linear
    unsigned char x_axis;    // associated x axis / or special command
    unsigned char y_axis;    // associated y axis
    unsigned char z_axis;    // associated z axis
    unsigned char a_axis;    // associated a axis
    unsigned char b_axis;    // associated b axis
    unsigned char c_axis;    // associated c axis
    unsigned char u_axis;    // associated u axis
    unsigned char v_axis;    // associated v axis
	short int special_param; // special param 0
	double t;   // time duration (in sec) of trip state
    double a;   // t^3 coefficient  (Jerk)
    double b;   // t^2 coefficient  (initial acceleration)
    double c;   // t^1 coefficient  (initial velocity)
    double d;   // t^0 constant coefficient (starting position)
    TRIP_CIRCLE_LINEAR X,Y;
    TRIP_LINEAR Z,A,B,C,U,V;
} PARAMETRIC_COEFF;

typedef struct  // 3rd order polynomial for a single trip state
{
    int trajectory_mode;
    double t;   // time duration (in sec) of trip state
    double a;   // t^3 coefficient  (Jerk)
    double b;   // t^2 coefficient  (initial acceleration)
    double c;   // t^1 coefficient  (initial velocity)
    double d;   // t^0 constant coefficient (starting position)
} TRIP_COEFF;

typedef struct  // 2nd order IIR Filter
{
    float A1;   // output coefficient Z-1
    float A2;   // output coefficient Z-2
    float B0;   // input  coefficient Z-0
    float B1;   // input  coefficient Z-1
    float B2;   // input  coefficient Z-2
    float d0,d1; // delay values
} IIR;

// MOTION TRAJECTORY STRUCTURES

extern double CS0_t;				// Current Coordinated Motion Segment Times
extern double CS0_TimeExecuted;		// Sum of all previous Coordinated Motion Segments Executed
extern double CS0_TimeDownloaded;	// Sum of all Coord Motion Segments downloaded from Host
extern double CS0_TimeLost;			// Sum of all Coord Motion Segments downloaded from Host that have been discarded (buffer wrap)
extern double CS0_TimeBase;      	// how much coordinated motion is advanced each tick
extern double CS0_TimeBaseDelta;  	// max amount coordinated motion time base is changed per tick
extern float CS0_DecelTime;			// how long to take to stop the coordinated motion (computed by StopMotion)
extern double CS0_TimeBaseDesired;	// Last Desired rate-of-time (TIMEBASE = real time)

extern BOOL CS0_DoingRapid;				// Flag indicating Rapid in Progress so use normal Time Base ignoring FRO (except for FeedHold)
extern BOOL CS0_Flushed;				// Coordinated motion Terminated so no longer necessary to worry about starvation
extern BOOL CS0_HoldAtEnd;				// Coordinated motion to not Terminate but rather Hold when reaching end of buffer

extern float CS0_NomDecel2TB2;			// Nominal Decel Time/(2 TIMEBASE^2) = Factor to relate buffer time to TimeBase to be able to stop

extern int CS0_StoppingState; 			// emergency stop in progress, 0 = not stopping, 1=stopping coord motion, 2=stopping indep, 3=fully stopped, 4=ind stopped
extern PARAMETRIC_COEFF *CoordSystem0;  // current pointer into Coordinated Motion
extern PARAMETRIC_COEFF *LastCoordSystem0;
extern int ParametricIndex;				// Index of where to put next downloaded Coord Motion Segment or command
extern BOOL ParametricIndexWrapped;		// Indicates that Coord Motion Buffer has wrapped and additional segments will cause segments to be lost
extern PARAMETRIC_COEFF *ParametricCoeffs;  // Points to beginning of Coord Motion Buffer
extern PARAMETRIC_COEFF *ParametricCoeffsEnd;  // Points to End+1 of Allocated Coord Motion Buffer (MAX_SEGMENTS)
extern PARAMETRIC_COEFF *LastCoordSystem0;  // Pointer to last Segment executed when finished
extern PARAMETRIC_COEFF *LastValidTrajSegment; // Last Segment actually Executed

void StopCoordinatedMotion(void);  	// bring any coordinated motion to a emergency stop ASAP
void ResumeCoordinatedMotion(void);	// resume coordinated/Indep motion after an emergency stop
void ClearStopImmediately(void);	// Clear Stop Condition without resuming
void UpdateStoppingState(void);		// Update Stopping Status (only required for indep stopping)
float GetNominalFROChangeTime(void);// computed time to change from FRO 1.0 to 0.0 for all defined CoordSystem Axes and their specified Vel, Accel, jerk
void SetFRO(float FRO); // change from current to the specified FRO (FRO=1.0=Realtime)using a nominal rate based on computed time to change from 1.0 to 0.0
void SetRapidFRO(float FRO); // change from current to the specified Rapid FRO (FRO=1.0=Realtime)using a nominal rate based on computed time to change from 1.0 to 0.0
void SetFROTemp(float FRO); // Temporarily change from current to the specified FRO using a nominal rate, override FeedHold, don't save as LastFRO
void SetFROwRate(float FRO, float DecelTime); // change from current to the specified FRO (FRO=1.0=Realtime)using a rate based on caller specified time to change from 1.0 to 0.0
void SetRapidFROwRate(float FRO, float DecelTime); // change from current to the specified Rapid FRO (FRO=1.0=Realtime)using a rate based on caller specified time to change from 1.0 to 0.0
void SetFROwRateTemp(float FRO, float DecelTime); //  Temporarily change from current to the specified FRO using a rate based on caller specified time, override FeedHold, don't save as LastFRO
extern float CS0_LastFRO;	        // Last Desired FRO (used for Resume after FeedHold or for changes in FRO while in FeedHold)
extern float CS0_LastRapidFRO;      // Last Desired FRO (used for Resume after FeedHold during Rapid)

// Called after adding something to the Cood Motion Buffer.  Increments the Coord Motion Buffer pointer
// while keeping track of how much time is currently in the buffer (CS0_TimeDownloaded), also how much
// was over written due to buffer wrapping (CS0_TimeLost) to be able to determine the extent that it is
// possible to reverse, and keep the buffer terminated with TRAJECTORY_OFF
void IncParametricIndex(void);

#define MAX_TRIP 20  // max trip states for individual axis moves
extern TRIP_COEFF TripCoeffs[N_CHANNELS][MAX_TRIP];  // Trip Coeff lists for each channel

// Limit Switch Options

// Bit 0 1=Stop Motor on Neg Limit, 0=Ignore Neg limit
// Bit 1 1=Stop Motor on Pos Limit, 0=Ignore Pos limit
// Bit 2 Neg Limit Polarity 0=stop on high, 1=stop on low
// Bit 3 Pos Limit Polarity 0=stop on high, 1=stop on low
//
// Bits 4-7 Action - 0 Kill Motor Drive
//                   1 Disallow drive in direction of limit
//                   2 Stop movement
//
// Bit 8=use Extended Limit Bit Numbers (LimitNegSwitchBit,LimitPosSwitchBit)
//
// (for legacy support allow packed 8-bit numbers)
// Bits 16-23 Neg Limit I/O Bit number
// Bits 24-31 Pos Limit I/O Bit number

//  M A I N   S T R U C T U R E   T H A T   D E F I N E S   A N   A X I S

typedef struct
{
    int ChanNumber;                 // channel number 0-3
    int Enable;                     // enables feedback
    int InputMode;                  // sets position input mode (See Axis Input Modes)
    int OutputMode;					// sets servo/motor mode    (See Axis Output Modes)
    int LimitSwitchOptions;         // see above for description
    int LimitSwitchNegBit;			// Neg Limit I/O Bit number
    int LimitSwitchPosBit;			// Pos Limit I/O Bit number
	int MasterAxis;					// -1 if none, else master axis channel to slave to
	double SlaveGain;				// Multiplicative Factor for slave motion
    double MaxFollowingError;       // Kill motor if error exceeds this value
    double LastFollowingError;      // Last Measured Following Error
    double t;                       // current time in secs within the trip state
    double Dest;                    // current dest position for servo
	double UnfilteredDest;			// unfiltered current dest position for servo (before CM smoothing)
    double DestOffset;              // Additional offset to position (used by Injection)
    float Vel;                      // max velocity for the move trajectory
    float Accel;                    // max Acceleration for the move trajectory
    float Jerk;                     // max Jerk (rate of change of Accel) for the move
    float FFAccel;                  // Acceleration feed forward
    float FFVel;                    // Velocity feed forward
    double Position;                // encoder, ADC, Resolver, reading
    double invDistPerCycle;         // for stepper distance for one complete cycle (4 full steps)
                                    // for brushless 3-4 phase encoder counts for one complete cycle
                                    // (saved as reciprical for speed)
    float StepperAmplitude;         // Microstepper Amplitude in PWM counts to apply (moving slow, without lead comp)
    float Output;                  	// Value output to PWM or DAC or CL Stepper offset
    float prev_output;              // previous Output so Slave can track Master when in CL Stepper
    float Lead;                     // Lead compensation to correct for step motor inductance
    TRIP_COEFF *pcoeff;             // pointer to coeff that interrupt routine uses, NULL if done
    double last_position;           // last measured error
    double last_dest;               // last destination from beginning of prev servo interrupt
	double prev_dest;				// prev destination from end of prev servo interrupt (will incl User changes to Dest)
	int LastNonZeroDir;				// Last direction we actually moved some amount(+1=Positive, 0=undefined, -1=negative)
	int DirectionOfMotion;			// Dest change was in this direction (+1=Positive, 0=none, -1=negative)
	float last_vel;                 // last destination velocity
    float x1last,x2last;            // used with lead compensation
    int   OutputChan0,OutputChan1;  // pwm or DAC channels to use
    int   InputChan0,InputChan1;    // Encoder or ADC channels to use
    float InputOffset0,InputGain0;  // offsets and gains for Resolver Input 0,1 (x'=ax+b)
    float InputOffset1,InputGain1;  //   or for ADC, or (InputGain0=-1 reverses encoder)
	float OutputGain;				// Scale or Reverse Output Magnitude or Direction
	float OutputOffset;				// Offset the output
    float CommutationOffset;        // 3 or 4 phase commutation offset, PhaseA = sin((Position+CommutationOffset)*invDistPerCycle)
    float last_theta;               // last resolver theta reading
    float theta_correction;         // resolver correction offset to correct for nonlinearities
    signed char last_enc;           // last fpga encoder reading
    float P,I,D;                    // pid gain values
    float MaxI;                     // max integrator windup
    float MaxErr;                   // error saturates at this value
    float integrator;               // current integrator vlue
    float MaxOutput;                // max allowed servo output
    float DeadBandRange;            // Range about zero where gain change occurs
    float DeadBandGain;             // Additional gain within DeadBand Range
	int LastMotionType;				// Type of last move - used in Immediate Stop/Resume
	double LastMotionDest;			// Where last move was to go - used in Immediate Stop/Resume
	float ExpMotionVc;				// Velocity point on exp curve where Max Accel is obtained
	float ExpMotionXc;				// Distance point on exponential curve where Max Accel is obtained
	float SoftLimitNeg;				// Negative Soft Limit (counts)
	float SoftLimitPos;				// Positive Soft Limit (counts)
	int BacklashMode;				// Type of correction:  Currently only BACKLASH_OFF, BACKLASH_LINEAR
	float BacklashAmount;			// Amount of Backlash to be applied
	float BacklashRate;				// Rate Backlash shoule be applied, counts/sec
	int BacklashDirection;			// Last non zero direction moved
	float PrevBacklashDest;			// Prev Destination where backlash was determined to allow small hysteresis
	float Backlash;					// current amount of compensation being applied

    TRIP_COEFF *c;               	// move profile polynomial coefficients list (up tp MAX_TRIP)
    IIR iir[N_IIR_FILTERS];         // several IIR filters
}CHAN;

// continuously sent by DMA to DACs
extern short int DAC_Buffer[N_DACS];   //  format    12 bits data
#define DAC(ch, v) DAC_Buffer[ch]=((v-2048)&0xfff)  // set DAC channel to value (range -2048/+2047)

extern int ADC_BufferIn[N_ADCS];     //  format   12 bits data
#define ADC(ch) (ADC_BufferIn[ch]-2048)   // return ADC reading of specified channel (range -2048/2047)extern int ADC_BufferIn[N_ADCS];     //  format   4-dummy bits 12 bits data 16 dummy

extern int ADC_BufferInSnap[2*N_ADCS_SNAP];   //  Snap Amp Current ADC format  16-bits data

#define FULL_RANGE_CURRENT 4.85f
#define MeasuredAxisAmps(axis) ((ADC(axis+4)+2048)*(FULL_RANGE_CURRENT/4096.0f))  // returns measured current in an axis (Amperes)

// On board Power Amp PWM control

#define MAX_PWMR_VALUE 400		// Max value for PWMs in Recirculate mode
void WritePWMR(int ch, int v);  // Write to PWM - Recirculate mode (+ or - power then shorted)
#define MAX_PWM_VALUE 230		// Max value for PWMs in antiphase mode
void WritePWM(int ch, int v);   // Write to PWM - locked anti-phase mode (+ power then - power)

#define MAX_PWMC_VALUE 1000		// Max value for PWMs in Current Mode (SnapAmps only)
void WritePWMC(int ch, int v);  // Write to PWM - Current Loop mode - Always optimal decay

extern int SnapAmpPresent;     				// 1 = SnapAmp Present 0= Not Present
void WriteSnapAmp(int add, int data);		// write a 16-bit word directly to SnapAmp FPGA
int ReadSnapAmp(int add);					// read a 16-bit word directly from SnapAmp FPGA

// Digital I/O bit PWM control (8 I/O bits on KFlop JP6 may be pulsed)

#define N_IO_PWMS 8				// Number of pwms that may be assigned to GPIO bits
#define IO_PWMS 0xD0  			// FPGA offset to IO PWM registers (2 bytes each - value, enable(bit0))
#define IO_PWMS_PRESCALE 0x2f  	// FPGA offset to IO PWM Pre-Scale clock divider 0-255, 0 = 16.6MHz, 1=8.33MHz, ...
#define IO_PWM_MAX_VALUE 255    // 0 = 0%, 255 = 100 % duty cycle

// addr to r/w encoder noise rejection filter value (0..255),
// Bit8 switches Encoders Ch4-7 from JP5 to JP6,
// Bit9 switches Encoders Ch0-3 from JP7 to JP4
#define ENC_NOISE_FILTER_ADD  0x05
#define ENC_0_3_JP4 0x200
#define ENC_4_7_JP6 0x100
#define ENC_NOISE_FILTER_DEFAULT_VAL 7 // noise rejection filter default value (100MHz/3/7/2 = 2MHz)

#define ENC_NOISE_ERR_ADD 0x08  // encoder sudden change by 2 error address
#define ENC_NOISE_ERR_BIT0 4 	// encoder sudden change by 2 error bit for encoder 0
#define ENC_NOISE_ERR_BIT1 5 	// encoder sudden change by 2 error bit for encoder 1
#define ENC_NOISE_ERR_BIT2 6 	// encoder sudden change by 2 error bit for encoder 2
#define ENC_NOISE_ERR_BIT3 7 	// encoder sudden change by 2 error bit for encoder 3

// FPGA Step and Direction Frequency Generators (8) are available
//
//
#define NSTEPDIR 8

// address of 6 bit pulse length 0-63= # 16.666MHz clocks,
// bit6 muxes generators 0-3 from JP7 to JP4 and JP6,
// bit7 reverses polarity (0=pulses low & Pos Dir high, 1=pulses high & Pos Dir Low)
#define STEP_PULSE_LENGTH_ADD 0x06

#define STEP_PULSE_LENGTH_DEFAULT 32 // default pulse length of ~ 2us

#define STEP_RATE_ADD 0x3c // write a 32 bit word - Bit31=enable, Bit27=Drive, Bits24-26=chan, 0-23= signed fraction of 16.666MHz
#define STEP_POSITION_ADD0 0x40 // read a 16 bit word - step count0 - 9 bits signed position and 7 bits of fraction
#define STEP_POSITION_ADD1 0x42 // read a 16 bit word - step count1 - 9 bits signed position and 7 bits of fraction
#define STEP_POSITION_ADD2 0x44 // read a 16 bit word - step count2 - 9 bits signed position and 7 bits of fraction
#define STEP_POSITION_ADD3 0x46 // read a 16 bit word - step count3 - 9 bits signed position and 7 bits of fraction
#define STEP_POSITION_ADD4 0x48 // read a 16 bit word - step count4 - 9 bits signed position and 7 bits of fraction
#define STEP_POSITION_ADD5 0x4a // read a 16 bit word - step count5 - 9 bits signed position and 7 bits of fraction
#define STEP_POSITION_ADD6 0x4c // read a 16 bit word - step count6 - 9 bits signed position and 7 bits of fraction
#define STEP_POSITION_ADD7 0x4e // read a 16 bit word - step count7 - 9 bits signed position and 7 bits of fraction

extern int KanalogPresent;     // 1=Kanalog Present
extern int KStepPresent;       // 1=KStep Present - set this to mux inputs into virtual bits 48-63

// Kanalog FPGA Registers for internal use only
#define KAN_TRIG_REG 0xA0		// triggers a transfer to/from Kanalog, 1-enables Kanalog, 2-enables RS232, 3-both
#define KAN_DAC_REGS 0x80  		// 8 - 12 bit r/w regs
#define KAN_FET_OPTO 0x88  		// 1 - 16 bit 15-8 FET drivers, 7-0 Opto Outputs
#define KAN_GPOUT    0x89  		// 1 - 8 bit   7-0 GP 3.3V OUTPUTS
#define KAN_ADC_REGS 0x90  		// 8 - 12 bit r/w regs
#define KAN_OPTOIN_GPIN 0x98  	// 1 - 16 bit 15-8 OptoInputs, 7-0 GP 3.3V inputs

// Kanalog IO Bit numbers
#define KAN_INPUTS 128			// 16 Bits 128-143 (128-135 GPIN, 136-143 Opto in)
#define KAN_NINPUTS 16			// 16 Input Bits
#define KAN_OUTPUTS 144			// 24 Bits 144-167 (144-151 Opto out, 152-159 FET/Relay Drivers, 160-167 GPOUT)
#define KAN_NOUTPUTS 24			// 24 output Bits

// 3 Phase manual control. Angle is specified in cycles.
// cycles is a double precision value an may be a very
// large number.  Only the fractional part will be used.
#define MAXV 230.0f // Max allowed 3 phase vector (512/2/sin(60) - EOFF*4)
void Write3PH(CHAN *ch0, float v, double angle_in_cycles); // put a voltage v on a 3 Phase motor at specified commutation angle
void Write4PH(CHAN *ch0, float v, double angle_in_cycles); // put a voltage v on a 4 Phase motor at specified commutation angle

extern int LastPWM[N_PWMS+2*N_PWMS_SNAP];    // +/- 255 counts

int ReadADC(int ch);           // User Programs should use ADC() command instead
void WriteDAC(int ch, int v);  // User Programs should use DAC() command instead

//  S P I N D L E   A N D   T H R E A D I N G   S U P P O R T

// main Spindle data structure which maintains Spindle
// Position Info and threading control

typedef struct
{
	double Position;			// position in revs
	double StartPosition;		// position in revs to begin threading
	double LastUpdatePosition;	// last position in revs where speed was computed
	double RevsPerCount;		// inverse of counts/rev
	double UpdateTick;			// which servo tic we should calc RPM
	double DeltaTicks;			// # Servo tics between speed measurement
	double AdjTimeFilt;			// Lead Adjusted, filtered, time
	double LastCSTime;			// Previous Coordinate System Time
	double *pEncoderPos;		// pointer to Spindle Position
	double K;					// Tau low pass filter coefficient
	float TrueSpeedRPS;			// last measured speed
	float InvBaseSpeedRPS;		// Reciprocal of Base speed of which trajectory was planned
	double InvBaseSpeedRPSK1;	// InvBaseSpeedRPS * (1-K)
	float InvUpdateTime;		// Reciprocal of update time to avoid division
	float Tau;					// Time constant for spindle filtering
	int Type;					// Type=0 None, Type=1 uses encoder to measure spindle position
	int ThreadingActive;		// True when threading is in progress

} SPINDLE;

extern SPINDLE Spindle;

void ConfigureSpindle(int Type, int Axis, float UpdateTimeSecs, float Tau, float CountsPerRev);  // configures for type of Spindle feedback
void TrigThreading(float BaseSpeedRPS); // triggers threading coordinated motion, BaseSpeed is the ideal Spindle speed thatthe motion was planned for

//  T I M E   F U N C T I O N S

double Time_sec();// returns total time since power up in seconds

void WaitUntil(double time_sec);// wait until a specified time

void Delay_sec(double sec);// Delay time in seconds

// (returns current time)
double WaitNextTimeSlice(void);// wait until a thread's new time slice begins

#define TIMER0  (*(volatile int *)0x42000010) // 32 bit raw hardware timer counts at CLOCKFREQ (see PC_DSP.h)

extern volatile double ServoTick;         // increments each servo interrupt
extern volatile unsigned int LastTimer0;  // Last timer value when the ServoTick was incremented

extern CHAN chan[N_CHANNELS];   // the axes channel related structures
extern CHAN *ch0;               // global pointer to axis 0
extern CHAN *ch1;               // global pointer to axis 1
extern CHAN *ch2;               // global pointer to axis 2
extern CHAN *ch3;               // global pointer to axis 3
extern CHAN *ch4;               // global pointer to axis 4
extern CHAN *ch5;               // global pointer to axis 5
extern CHAN *ch6;               // global pointer to axis 6
extern CHAN *ch7;               // global pointer to axis 7

// This status contains the majority of all status
// so that it can be uploaded as a bulk transfer
extern MAIN_STATUS MainStatus;

void DisableAxis(int ch); // Disable the Axis, Servo output is set to zero

void EnableAxisDest(int ch, double Dest); // enable the Axis and set the destination

void EnableAxis(int ch); // enable the Axis at the current encoder position

// do this before enabling servo or when
// filter coefficients change
void ResetFilters(int ch); // Resets Filter history to known state

void Zero(int ch);  // Zero the Encoder Position and Current Commanded Position

// Basic motion commands to move one axis
void Move(int ch, double x);   // move using absolute coordinates
void MoveAtVel(int chno, double x, float MaxVel);        // move using absolute coordinates and specify the velocity
void MoveRel(int ch, double dx);    // move relative to current destination
void MoveRelAtVel(int chno, double x, float MaxVel);        //  move relative to current destinatio and specify the velocity
void Jog(int ch, double vel);       // move continiously at specified velocity
void MoveExp(int chno, double x, double Tau);  // exponentially approach a target at time constant Tau

int CheckDone(int ch);  // returns 1 if axis is Done, 0 if not, -1 if axis is disabled

// Basic motion commands to move 3 axes
//
void MoveXYZABC(double x, double y, double z, double a, double b, double c); // Moves 6 axes (each axis moves independently)
int CheckDoneXYZABC(); // Check if all CS axis have completed , returns 1 if all complete, -1 if any is disabled, otherwise 0

int CheckDoneBuf();   // returns 1 if Done, 0 if not, -1 if any axis in CS disabled
int CheckDoneGather();
void StartMove(int ch);

void SetupForMove(double From, double To, float MaxVel, CHAN *ch, int CoeffOffset,
                                                  int NoJerkControlAtStart,
                                                  int NoJerkControlAtEnd,
                                                  int Start,
												  int *Nstates);

void SetupForMotionPause(double x,CHAN *ch,int CoeffOffset, double time);  // stay still

// coordinate systems #0 - axis definitions
extern int CS0_axis_x; // Axis channel number to use as x
extern int CS0_axis_y; // Axis channel number to use as y
extern int CS0_axis_z; // Axis channel number to use as z
extern int CS0_axis_a; // Axis channel number to use as a
extern int CS0_axis_b; // Axis channel number to use as b
extern int CS0_axis_c; // Axis channel number to use as c
extern int CS0_axis_u; // Axis channel number to use as u
extern int CS0_axis_v; // Axis channel number to use as v

void DefineCoordSystem(int axisx, int axisy, int axisz, int axisa); // define axis chan numbers to use as x,y,z,a (set -1 to disable)
void DefineCoordSystem6(int axisx, int axisy, int axisz, int axisa, int axisb, int axisc); // define axis chan numbers to use as x,y,z,a,b,c (set -1 to disable)
void DefineCoordSystem8(int axisx, int axisy, int axisz, int axisa, int axisb, int axisc, int axisu, int axisv); // define axis chan numbers to use as x,y,z,a,b,c,u,v (set -1 to disable)

// A Low Pass filter can be applied to all 8 axes of coordinated motion
// by setting the KLP coefficient.  To compute an appropriate coefficient
// from a time constant Tau in seconds use KLP = exp(-TIMEBASE/Tau);

extern double KLP;  // coordinated motion low pass filter coefficient

// TauKLP = -TIMEBASE/log(KLP);  automatically computed by ExecBuf command
extern float TauKLP;		    // "smoothing" related time constant used for End Motion

extern float SplineTauFactor;  // Final Spline motion to target will have a time duration of this number of TauKLP (defaults to 2)

// Stop profile generation
// which will stop updating (freeze) the destination
// new commands can then be placed into the queue

void StopMotion(CHAN *ch);

// put a trajectory off into the queue

void SetupForMotionEnd(CHAN *ch, int CoeffOffset) ;

// Digital I/O Functions

#define BIT_SET  0x100      // rel address in FPGA where bit set ports reside
#define BIT_CLR  0x110      // rel address in FPGA where bit clear ports reside
#define BIT_DIR  0x120      // rel address in FPGA where bit Direction ports reside
#define BIT_READ 0x130      // rel address in FPGA where bit read ports reside

// Fixed I/O bit definitions

#define LED0 46  // KFLOP LED #0 bit number
#define LED1 47	 // KFLOP LED #1 bit number

// Virtual I/O bits
extern int VirtualBits;   		// Virtual I/O bits simulated in memory, use SetBit/ClearBit/SetStateBit(32-63 to reference)

// Virtual I/O bits Extended 1024-2047
extern int VirtualBitsEx[N_VIRTUAL_BITS_EX/32];	// 1024 Expanded Virtual Bits (1024-2047)

extern int BitDirShadow[2];  	// direction of all 64 I/O bits
extern int BitDirShadowSnap0;  	// direction of 14 Snap Amp, 1st board, I/O bits
extern int BitDirShadowSnap1;  	// direction of 14 Snap Amp, 2nd board, I/O bits

void SetBitDirection(int bit, int dir); // define bit as input (0) or output (1)
int GetBitDirection(int bit);           // returns whether bit is defined as input (0) or output (1)
void SetBit(int bit);                   // set a bit high (bit must be defined as an output, see SetBitDirection)
void ClearBit(int bit);                 // set a bit low (bit must be defined as an output, see SetBitDirection)
void SetStateBit(int bit, int state);   // set a bit high or low (bit must be defined as an output, see SetBitDirection)
int ReadBit(int bit);                   // read the state of an I/O bit

// KONNECT AUX PORT FUNCTIONS
//
// Example:
//
// Configure KFLOP to service Konnect 32 Input 16 output IO board
// Board address is 0,
// 16 Outputs are mapped to Virtual IO 48-63 (VirtualBits)
// 32 Inputs are mapped to Virtual IO 1024-1055 (VirtualBits[0])
//
//		InitAux();
//		AddKonnect(0,&VirtualBits,VirtualBitsEx);
//

void InitAux(void);  // Initialize the AUX Port KFLOP JP4 or JP6 and clear list of board to be serviced (only one Aux Port may be used at a time)

// Board address, address of 32-bit into to get the Output Bits (in low 16 bits), address of where to put 32 Inputs
void AddKonnect(int BoardAddress, int *OutputAddress, int *InputAddress);  // add a Konnect Board to list of AUX1 Port Boards to be serviced

// Board address, address of 32-bit into to get the Output Bits (in low 16 bits), address of where to put 32 Inputs
void AddKonnect_Aux0(int BoardAddress, int *OutputAddress, int *InputAddress); // add a Konnect Board to list of AUX0 Port Boards to be serviced

// User Print Routines
//
// sends a string to the user console of the KMotion
// application.  Because other threads may be sending
// characters, the strings are buffered in a queue
// and sent by the primary thread as soon as there
// is no PC input to process.  The string prepends
// an escape so the PC application knows for sure
// to send this to the Console window and not to
// process it as a response to a command that may
// be in the pipeline.
//
//
// normally the routine exits to the caller quickly
// unless the queue is full, then it must wait

#define MAX_STRING 128
#define MAX_NSTRINGS 256  // must be binary

// Note: standard C language printf

int printf(const char *format, ...);     		// Print formatted string to console
int sprintf(char *s, const char *format, ...); 	// Print formatted string to string

typedef int FILE;
FILE *fopen(const char*, const char*);		   // Open a text file for writing on the PC (2nd param is ignored)
int fprintf(FILE *f, const char * format, ...);		   // Print formatted string to the PC's Disk File
int fclose(FILE *f);                           // Close the disk file on the PC

int Print(char *s);                      		// Print a string to the console window
int PrintFloat(char *Format, double v);  		// Print a double using printf format, ex "%8.3f\n"
int PrintInt(char *Format, int v);       		// Print an integer using printf format, ex "result=%4d\n"

int sscanf(const char *_str, const char *_fmt, ...); //scan string and convert to values

/*
 * MessageBox() Flags thes can be passed to the PC to invoke MessageBoxes
 *              for some applications such as KMotionCNC which monitor upload
 *              status and present message boxes when requested.  See the pc-dsp.h
 *              header for more information
 */
#define MB_OK                       0x00000000L
#define MB_OKCANCEL                 0x00000001L
#define MB_ABORTRETRYIGNORE         0x00000002L
#define MB_YESNOCANCEL              0x00000003L
#define MB_YESNO                    0x00000004L
#define MB_RETRYCANCEL              0x00000005L
#define MB_CANCELTRYCONTINUE        0x00000006L
#define MB_ICONHAND                 0x00000010L
#define MB_ICONQUESTION             0x00000020L
#define MB_ICONEXCLAMATION          0x00000030L
#define MB_ICONASTERISK             0x00000040L
#define MB_APPLMODAL                0x00000000L
#define MB_SYSTEMMODAL              0x00001000L
#define MB_TASKMODAL                0x00002000L
#define MB_NOFOCUS                  0x00008000L
#define MB_SETFOREGROUND            0x00010000L
#define MB_DEFAULT_DESKTOP_ONLY     0x00020000L
#define MB_TOPMOST                  0x00040000L
#define MB_RIGHT                    0x00080000L

/*
 * Dialog Box Command IDs
 */
#define IDOK                1
#define IDCANCEL            2
#define IDABORT             3
#define IDRETRY             4
#define IDIGNORE            5
#define IDYES               6
#define IDNO                7

// Misc routines

void DoResolverInput2(CHAN *chx, float x, float y);  // optimized routine to handle sin/cosine resolver input

extern double ResolverFactor; // defaults to 1000.0/TWO_PI converts sine/cosine angle to reported Position

// M U L T I - T H R E A D   S U P P O R T

// user threads are numbered 1 .. n

void StartThread(int thread);  // starts a downloaded program at it's entry point
void PauseThread(int thread);  // stops a thread from executing
int ResumeThread(int thread);  // resumes a tread after a pause
void ThreadDone(void);         // call to terminate current thread

// A User Program Call Back can be defined to be called every Servo Sample
// Set to Non-NULL for the the Callback to be made.  The Callback Routine
// must return with a few micro seconds or the system may become unstable
typedef void USERCALLBACK(void);
extern USERCALLBACK *UserCallBack;

// used to allow mutual exclusive access to a resource
// (waits until resource is available, then locks it)
// if the thread that locked it is no longer active,
// release the lock

void MutexLock(int *mutex);
void MutexUnlock(int *mutex);

// These routines are written in assembly such that
// they are atomic and are un-interruptible by using
// instructions in delayed branching

void AtomicSet(int *p, int mask);
//{
//	*p = *p | mask;
//}

void AtomicClear(int *p, int mask);
//{
//	*p = *p & mask;
//}

// test a location and if zero, set
// to value.  returns the original
// value.  routine is atomic

int TestAndSet(int *mutex, int value);
//{
//	register result = *mutex;
//	if (result==0) *mutex=value;
//	return result;
//}

// S N A P   A M P   D E F I N I T I O N S

#define KM_SNAP_READ_LOW 0xc
#define KM_SNAP_READ_HI  0xd
#define KM_SNAP_READ_EXCEPTION 0x10
#define KM_SNAP_CLK_ENA 0x09
#define KM_SNAP_SHIFT_BYTE 0x0a
#define KM_SNAP_WRITE_HIGH_TRIG 0x0b
#define KM_SNAP_READ_ADD_TRIG 0x0c
#define KM_SNAP_READ_ADD_BITMAP 0x28
// FPGA Registers

#define SNAP0 0x40  // Base Addresse SNAP AMP #0
#define SNAP1 0x60  // Base Addresse SNAP AMP #1

// write addresses

#define SNAP_PWMS 0 			 	// (4) 16 bit PWMs
#define SNAP_CLR_ENC_ERRS 8			// any write clears all encoder errors
#define SNAP_CUR_LOOP_GAINS 9		// (4) 8 bit Current Loop Gains Default=16
#define SNAP_SET_BIT 17				// (14) GPIO bits
#define SNAP_CLR_BIT 18				// (14) GPIO bits
#define SNAP_DIR_BIT 19				// (14) GPIO bits
#define SNAP_SUPPLY_CLAMP0 20		// 16 bit power supply clamp setting side A
#define SNAP_SUPPLY_CLAMP_ENA0 21	// 1 bit power supply clamp enable side A
#define SNAP_SUPPLY_CLAMP1 22		// 16 bit power supply clamp setting side B
#define SNAP_SUPPLY_CLAMP_ENA1 23	// 1 bit power supply clamp enable side B
#define SNAP_PEAK_CUR_LIMIT0 24		// 4 bits peak current limit side A
#define SNAP_PEAK_CUR_LIMIT1 25		// 4 bits peak current limit side B

// read addresses

#define SNAP_PWMS 0 		 		// (4) 16 bit PWMs
#define SNAP_ENC 8 		 			// (4) 16 bit Encoders (bit15=error 7-0=data)
#define SNAP_CURRENT_A0 12			// Measured Current Side A Lead A (14bits)
#define SNAP_CURRENT_C0 13			// Measured Current Side A Lead C
#define SNAP_CURRENT_A1 14			// Measured Current Side B Lead A
#define SNAP_CURRENT_C1 15			// Measured Current Side B Lead C
#define SNAP_DIFF_IN 16 		 	// 16 bits (15-8= Diff inputs 7-0=encoder inputs)
#define SNAP_IN_BIT 17				// (14) GPIO bits
#define SNAP_SUPPLY_VOLT0 22		// Measured Supply Voltage Side A
#define SNAP_SUPPLY_VOLT1 23		// Measured Supply Voltage Side B
#define SNAP_TEMP0 24				// Measured Temperature Side A
#define SNAP_TEMP1 25				// Measured Temperature Side B
#define SNAP_STATUS 30				// Status (FAN,OverTemp1,OverTemp0,OVER_CUR1,OVER_CUR0,Fault)
#define SNAP_RESET 31				// Reset

//RS232 FPGA Register Definitions

#define RS232_STATUS 0xc1		// Status Reg Address
#define RS232_DATA 0xc0			// 8 bit data read/write reg address
#define RS232_DATA_READY 0x01	// Data ready to read status mask
#define RS232_TRANSMIT_FULL 0x02// Transmit buffer full status mask

#define RS232_BAUD_REG 0xc1	// Set Baud rate 8-bit divisor Reg Address
#define RS232_BAUD_115200 	((16666666/115200/16)-1)// 8-bit divisor value to set 115200 baud
#define RS232_BAUD_57600 	((16666666/57600/16)-1)	// 8-bit divisor value to set  57600 baud
#define RS232_BAUD_38400 	((16666666/38400/16)-1)	// 8-bit divisor value to set  38400 baud
#define RS232_BAUD_19200 	((16666666/19200/16)-1)	// 8-bit divisor value to set  19200 baud
#define RS232_BAUD_9600 	((16666666/9600/16)-1)	// 8-bit divisor value to set   9600 baud
#define RS232_BAUD_4800 	((16666666/4800/16)-1)	// 8-bit divisor value to set   4800 baud

void InitRS232(int baud);
void EnableRS232Cmds(int baud);

extern char * volatile pRS232RecIn;  // Buffered Receive Pointer Head
extern char *pRS232RecOut;           // Buffered Receive Pointer Tail
extern char *pRS232TxIn;             // Buffered Transmit Pointer Head
extern char * volatile pRS232TxOut;  // Buffered Transmit Pointer Tail
extern int DoRS232Cmds;              // Enables/disables KFLOP Command processor to/from RS232

char RS232_GetChar(void);   // Get Internally Buffered (1000 chars) RS232 received Data
void RS232_PutChar(char c); // Put Internally Buffered (1000 chars) RS232 transmit Data

#endif


text:
require File.join(File.dirname(__FILE__), 'test_helper')

class Widget < ActiveRecord::Base
  acts_as_paranoid
  has_many :categories, :dependent => :destroy
  has_and_belongs_to_many :habtm_categories, :class_name => 'Category'
  has_one :category
  belongs_to :parent_category, :class_name => 'Category'
  has_many :taggings
  has_many :tags, :through => :taggings
  has_many :any_tags, :through => :taggings, :class_name => 'Tag', :source => :tag, :with_deleted => true
end

class Category < ActiveRecord::Base
  belongs_to :widget
  belongs_to :any_widget, :class_name => 'Widget', :foreign_key => 'widget_id', :with_deleted => true
  acts_as_paranoid

  def self.search(name, options = {})
    find :all, options.merge(:conditions => ['LOWER(title) LIKE ?', "%#{name.to_s.downcase}%"])
  end

  def self.search_with_deleted(name, options = {})
    find_with_deleted :all, options.merge(:conditions => ['LOWER(title) LIKE ?', "%#{name.to_s.downcase}%"])
  end
end

class Tag < ActiveRecord::Base
  has_many :taggings
  has_many :widgets, :through => :taggings
end

class Tagging < ActiveRecord::Base
  belongs_to :tag
  belongs_to :widget
  acts_as_paranoid
end

class NonParanoidAndroid < ActiveRecord::Base
end

class ParanoidTest < Test::Unit::TestCase
  fixtures :widgets, :categories, :categories_widgets, :tags, :taggings

  def test_should_recognize_with_deleted_option
    assert_equal [1, 2], Widget.find(:all, :with_deleted => true).collect { |w| w.id }
    assert_equal [1], Widget.find(:all, :with_deleted => false).collect { |w| w.id }
  end

  def test_should_recognize_only_deleted_option
    assert_equal [2], Widget.find(:all, :only_deleted => true).collect { |w| w.id }
    assert_equal [1], Widget.find(:all, :only_deleted => false).collect { |w| w.id }
  end

  def test_should_exists_with_deleted
    assert Widget.exists_with_deleted?(2)
    assert !Widget.exists?(2)
  end

  def test_should_exists_only_deleted
    assert Widget.exists_only_deleted?(2)
    assert !Widget.exists_only_deleted?(1)
  end

  def test_should_count_with_deleted
    assert_equal 1, Widget.count
    assert_equal 2, Widget.count_with_deleted
    assert_equal 1, Widget.count_only_deleted
    assert_equal 2, Widget.calculate_with_deleted(:count, :all)
  end

  def test_should_set_deleted_at
    assert_equal 1, Widget.count
    assert_equal 1, Category.count
    widgets(:widget_1).destroy
    assert_equal 0, Widget.count
    assert_equal 0, Category.count
    assert_equal 2, Widget.calculate_with_deleted(:count, :all)
    assert_equal 4, Category.calculate_with_deleted(:count, :all)
  end

  def test_should_destroy
    assert_equal 1, Widget.count
    assert_equal 1, Category.count
    widgets(:widget_1).destroy!
    assert_equal 0, Widget.count
    assert_equal 0, Category.count
    assert_equal 1, Widget.count_only_deleted
    assert_equal 1, Widget.calculate_with_deleted(:count, :all)
    # Category doesn't get destroyed because the dependent before_destroy callback uses #destroy
    assert_equal 4, Category.calculate_with_deleted(:count, :all)
  end

  def test_should_delete_all
    assert_equal 1, Widget.count
    assert_equal 2, Widget.calculate_with_deleted(:count, :all)
    assert_equal 1, Category.count
    Widget.delete_all
    assert_equal 0, Widget.count
    # delete_all doesn't call #destroy, so the dependent callback never fires
    assert_equal 1, Category.count
    assert_equal 2, Widget.calculate_with_deleted(:count, :all)
  end

  def test_should_delete_all_with_conditions
    assert_equal 1, Widget.count
    assert_equal 2, Widget.calculate_with_deleted(:count, :all)
    Widget.delete_all("id < 3")
    assert_equal 0, Widget.count
    assert_equal 2, Widget.calculate_with_deleted(:count, :all)
  end

  def test_should_delete_all2
    assert_equal 1, Category.count
    assert_equal 4, Category.calculate_with_deleted(:count, :all)
    Category.delete_all!
    assert_equal 0, Category.count
    assert_equal 0, Category.calculate_with_deleted(:count, :all)
  end

  def test_should_delete_all_with_conditions2
    assert_equal 1, Category.count
    assert_equal 4, Category.calculate_with_deleted(:count, :all)
    Category.delete_all!("id < 3")
    assert_equal 0, Category.count
    assert_equal 2, Category.calculate_with_deleted(:count, :all)
  end

  def test_should_not_count_deleted
    assert_equal 1, Widget.count
    assert_equal 1, Widget.count(:all, :conditions => ['title=?', 'widget 1'])
    assert_equal 2, Widget.calculate_with_deleted(:count, :all)
    assert_equal 1, Widget.count_only_deleted
  end

  def test_should_find_only_deleted
    assert_equal [2], Widget.find_only_deleted(:all).collect { |w| w.id }
    assert_equal [1, 2], Widget.find_with_deleted(:all, :order => 'id').collect { |w| w.id }
  end

  def test_should_not_find_deleted
    assert_equal [widgets(:widget_1)], Widget.find(:all)
    assert_equal [1, 2], Widget.find_with_deleted(:all, :order => 'id').collect { |w| w.id }
  end

  def test_should_not_find_deleted_has_many_associations
    assert_equal 1, widgets(:widget_1).categories.size
    assert_equal [categories(:category_1)], widgets(:widget_1).categories
  end

  def test_should_not_find_deleted_habtm_associations
    assert_equal 1, widgets(:widget_1).habtm_categories.size
    assert_equal [categories(:category_1)], widgets(:widget_1).habtm_categories
  end

  def test_should_not_find_deleted_has_many_through_associations
    assert_equal 1, widgets(:widget_1).tags.size
    assert_equal [tags(:tag_2)], widgets(:widget_1).tags
  end

  def test_should_find_has_many_through_associations_with_deleted
    assert_equal 2, widgets(:widget_1).any_tags.size
    assert_equal Tag.find(:all), widgets(:widget_1).any_tags
  end

  def test_should_not_find_deleted_belongs_to_associations
    assert_nil Category.find_with_deleted(3).widget
  end

  def test_should_find_belongs_to_assocation_with_deleted
    assert_equal Widget.find_with_deleted(2), Category.find_with_deleted(3).any_widget
  end

  def test_should_find_first_with_deleted
    assert_equal widgets(:widget_1), Widget.find(:first)
    assert_equal 2, Widget.find_with_deleted(:first, :order => 'id desc').id
  end

  def test_should_find_single_id
    assert Widget.find(1)
    assert Widget.find_with_deleted(2)
    assert_raises(ActiveRecord::RecordNotFound) { Widget.find(2) }
  end

  def test_should_find_multiple_ids
    assert_equal [1,2], Widget.find_with_deleted(1,2).sort_by { |w| w.id }.collect { |w| w.id }
    assert_equal [1,2], Widget.find_with_deleted([1,2]).sort_by { |w| w.id }.collect { |w| w.id }
    assert_raises(ActiveRecord::RecordNotFound) { Widget.find(1,2) }
  end

  def test_should_ignore_multiple_includes
    Widget.class_eval { acts_as_paranoid }
    assert Widget.find(1)
  end

  def test_should_not_override_scopes_when_counting
    assert_equal 1, Widget.send(:with_scope, :find => { :conditions => "title = 'widget 1'" }) { Widget.count }
    assert_equal 0, Widget.send(:with_scope, :find => { :conditions => "title = 'deleted widget 2'" }) { Widget.count }
    assert_equal 1, Widget.send(:with_scope, :find => { :conditions => "title = 'deleted widget 2'" }) { Widget.calculate_with_deleted(:count, :all) }
  end

  def test_should_not_override_scopes_when_finding
    assert_equal [1], Widget.send(:with_scope, :find => { :conditions => "title = 'widget 1'" }) { Widget.find(:all) }.ids
    assert_equal [],  Widget.send(:with_scope, :find => { :conditions => "title = 'deleted widget 2'" }) { Widget.find(:all) }.ids
    assert_equal [2], Widget.send(:with_scope, :find => { :conditions => "title = 'deleted widget 2'" }) { Widget.find_with_deleted(:all) }.ids
  end

  def test_should_allow_multiple_scoped_calls_when_finding
    Widget.send(:with_scope, :find => { :conditions => "title = 'deleted widget 2'" }) do
      assert_equal [2], Widget.find_with_deleted(:all).ids
      assert_equal [2], Widget.find_with_deleted(:all).ids, "clobbers the constrain on the unmodified find"
      assert_equal [], Widget.find(:all).ids
      assert_equal [], Widget.find(:all).ids, 'clobbers the constrain on a paranoid find'
    end
  end

  def test_should_allow_multiple_scoped_calls_when_counting
    Widget.send(:with_scope, :find => { :conditions => "title = 'deleted widget 2'" }) do
      assert_equal 1, Widget.calculate_with_deleted(:count, :all)
      assert_equal 1, Widget.calculate_with_deleted(:count, :all), "clobbers the constrain on the unmodified find"
      assert_equal 0, Widget.count
      assert_equal 0, Widget.count, 'clobbers the constrain on a paranoid find'
    end
  end

  def test_should_give_paranoid_status
    assert Widget.paranoid?
    assert !NonParanoidAndroid.paranoid?
  end

  def test_should_give_record_status
    assert_equal false, Widget.find(1).deleted?
    Widget.find(1).destroy
    assert Widget.find_with_deleted(1).deleted?
  end

  def test_should_find_deleted_has_many_assocations_on_deleted_records_by_default
    w = Widget.find_with_deleted 2
    assert_equal 2, w.categories.find_with_deleted(:all).length
    assert_equal 2, w.categories.find_with_deleted(:all).size
  end

  def test_should_find_deleted_habtm_assocations_on_deleted_records_by_default
    w = Widget.find_with_deleted 2
    assert_equal 2, w.habtm_categories.find_with_deleted(:all).length
    assert_equal 2, w.habtm_categories.find_with_deleted(:all).size
  end

  def test_dynamic_finders
    assert     Widget.find_by_id(1)
    assert_nil Widget.find_by_id(2)
  end

  def test_custom_finder_methods
    w = Widget.find_with_deleted(:all).inject({}) { |all, w| all.merge(w.id => w) }
    assert_equal [1],       Category.search('c').ids
    assert_equal [1,2,3,4], Category.search_with_deleted('c', :order => 'id').ids
    assert_equal [1],       widgets(:widget_1).categories.search('c').collect(&:id)
    assert_equal [1,2],     widgets(:widget_1).categories.search_with_deleted('c').ids
    assert_equal [],        w[2].categories.search('c').ids
    assert_equal [3,4],     w[2].categories.search_with_deleted('c').ids
  end
end

class Array
  def ids
    collect &:id
  end
end

redpajama_set_name: RedPajamaGithub


text:
package com.google.gerrit.acceptance.rest.project;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.gerrit.extensions.client.ListChangesOption.MESSAGES;

import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.access.AccessSectionInfo;
import com.google.gerrit.extensions.api.access.PermissionInfo;
import com.google.gerrit.extensions.api.access.PermissionRuleInfo;
import com.google.gerrit.extensions.api.access.ProjectAccessInfo;
import com.google.gerrit.extensions.api.access.ProjectAccessInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.projects.BranchInfo;
import com.google.gerrit.extensions.api.projects.ProjectApi;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.config.AllProjectsNameProvider;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.group.SystemGroupBackend;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Before;
import org.junit.Test;

public class AccessIT extends AbstractDaemonTest {

  private static final String PROJECT_NAME = "newProject";

  private static final String REFS_ALL = Constants.R_REFS + "*";
  private static final String REFS_HEADS = Constants.R_HEADS + "*";

  private static final String LABEL_CODE_REVIEW = "Code-Review";

  private String newProjectName;
  private ProjectApi pApi;

  @Before
  public void setUp() throws Exception {
    newProjectName = createProject(PROJECT_NAME).get();
    pApi = gApi.projects().name(newProjectName);
  }

  @Test
  public void getDefaultInheritance() throws Exception {
    String inheritedName = pApi.access().inheritsFrom.name;
    assertThat(inheritedName).isEqualTo(AllProjectsNameProvider.DEFAULT);
  }

  @Test
  public void addAccessSection() throws Exception {
    Project.NameKey p = new Project.NameKey(newProjectName);
    RevCommit initialHead = getRemoteHead(p, RefNames.REFS_CONFIG);

    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    pApi.access(accessInput);

    assertThat(pApi.access().local).isEqualTo(accessInput.add);

    RevCommit updatedHead = getRemoteHead(p, RefNames.REFS_CONFIG);
    eventRecorder.assertRefUpdatedEvents(
        p.get(), RefNames.REFS_CONFIG, null, initialHead, initialHead, updatedHead);
  }

  @Test
  public void createAccessChange() throws Exception {
    // User can see the branch
    setApiUser(user);
    gApi.projects().name(newProjectName).branch("refs/heads/master").get();

    ProjectAccessInput accessInput = newProjectAccessInput();

    AccessSectionInfo accessSection = newAccessSectionInfo();

    // Deny read to registered users.
    PermissionInfo read = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.DENY, false);
    read.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    read.exclusive = true;
    accessSection.permissions.put(Permission.READ, read);
    accessInput.add.put(REFS_HEADS, accessSection);

    setApiUser(user);
    ChangeInfo out = pApi.accessChange(accessInput);

    assertThat(out.project).isEqualTo(newProjectName);
    assertThat(out.branch).isEqualTo(RefNames.REFS_CONFIG);
    assertThat(out.status).isEqualTo(ChangeStatus.NEW);
    assertThat(out.submitted).isNull();

    setApiUser(admin);

    ChangeInfo c = gApi.changes().id(out._number).get(MESSAGES);
    assertThat(c.messages.stream().map(m -> m.message)).containsExactly("Uploaded patch set 1");

    ReviewInput reviewIn = new ReviewInput();
    reviewIn.label("Code-Review", (short) 2);
    gApi.changes().id(out._number).current().review(reviewIn);
    gApi.changes().id(out._number).current().submit();

    // check that the change took effect.
    setApiUser(user);
    try {
      BranchInfo info = gApi.projects().name(newProjectName).branch("refs/heads/master").get();
      fail("wanted failure, got " + newGson().toJson(info));
    } catch (ResourceNotFoundException e) {
      // OK.
    }

    // Restore.
    accessInput.add.clear();
    accessInput.remove.put(REFS_HEADS, accessSection);
    setApiUser(user);

    pApi.accessChange(accessInput);

    setApiUser(admin);
    out = pApi.accessChange(accessInput);

    gApi.changes().id(out._number).current().review(reviewIn);
    gApi.changes().id(out._number).current().submit();

    // Now it works again.
    setApiUser(user);
    gApi.projects().name(newProjectName).branch("refs/heads/master").get();
  }

  @Test
  public void removePermission() throws Exception {
    // Add initial permission set
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    pApi.access(accessInput);

    // Remove specific permission
    AccessSectionInfo accessSectionToRemove = newAccessSectionInfo();
    accessSectionToRemove.permissions.put(
        Permission.LABEL + LABEL_CODE_REVIEW, newPermissionInfo());
    ProjectAccessInput removal = newProjectAccessInput();
    removal.remove.put(REFS_HEADS, accessSectionToRemove);
    pApi.access(removal);

    // Remove locally
    accessInput.add.get(REFS_HEADS).permissions.remove(Permission.LABEL + LABEL_CODE_REVIEW);

    // Check
    assertThat(pApi.access().local).isEqualTo(accessInput.add);
  }

  @Test
  public void removePermissionRule() throws Exception {
    // Add initial permission set
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    pApi.access(accessInput);

    // Remove specific permission rule
    AccessSectionInfo accessSectionToRemove = newAccessSectionInfo();
    PermissionInfo codeReview = newPermissionInfo();
    codeReview.label = LABEL_CODE_REVIEW;
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.DENY, false);
    codeReview.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    accessSectionToRemove.permissions.put(Permission.LABEL + LABEL_CODE_REVIEW, codeReview);
    ProjectAccessInput removal = newProjectAccessInput();
    removal.remove.put(REFS_HEADS, accessSectionToRemove);
    pApi.access(removal);

    // Remove locally
    accessInput
        .add
        .get(REFS_HEADS)
        .permissions
        .get(Permission.LABEL + LABEL_CODE_REVIEW)
        .rules
        .remove(SystemGroupBackend.REGISTERED_USERS.get());

    // Check
    assertThat(pApi.access().local).isEqualTo(accessInput.add);
  }

  @Test
  public void removePermissionRulesAndCleanupEmptyEntries() throws Exception {
    // Add initial permission set
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    pApi.access(accessInput);

    // Remove specific permission rules
    AccessSectionInfo accessSectionToRemove = newAccessSectionInfo();
    PermissionInfo codeReview = newPermissionInfo();
    codeReview.label = LABEL_CODE_REVIEW;
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.DENY, false);
    codeReview.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    pri = new PermissionRuleInfo(PermissionRuleInfo.Action.DENY, false);
    codeReview.rules.put(SystemGroupBackend.PROJECT_OWNERS.get(), pri);
    accessSectionToRemove.permissions.put(Permission.LABEL + LABEL_CODE_REVIEW, codeReview);
    ProjectAccessInput removal = newProjectAccessInput();
    removal.remove.put(REFS_HEADS, accessSectionToRemove);
    pApi.access(removal);

    // Remove locally
    accessInput.add.get(REFS_HEADS).permissions.remove(Permission.LABEL + LABEL_CODE_REVIEW);

    // Check
    assertThat(pApi.access().local).isEqualTo(accessInput.add);
  }

  @Test
  public void getPermissionsWithDisallowedUser() throws Exception {
    // Add initial permission set
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createAccessSectionInfoDenyAll();

    // Disallow READ
    accessInput.add.put(REFS_ALL, accessSectionInfo);
    pApi.access(accessInput);

    setApiUser(user);
    exception.expect(ResourceNotFoundException.class);
    gApi.projects().name(newProjectName).access();
  }

  @Test
  public void setPermissionsWithDisallowedUser() throws Exception {
    // Add initial permission set
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createAccessSectionInfoDenyAll();

    // Disallow READ
    accessInput.add.put(REFS_ALL, accessSectionInfo);
    pApi.access(accessInput);

    // Create a change to apply
    ProjectAccessInput accessInfoToApply = newProjectAccessInput();
    AccessSectionInfo accessSectionInfoToApply = createDefaultAccessSectionInfo();
    accessInfoToApply.add.put(REFS_HEADS, accessSectionInfoToApply);

    setApiUser(user);
    exception.expect(ResourceNotFoundException.class);
    gApi.projects().name(newProjectName).access();
  }

  @Test
  public void permissionsGroupMap() throws Exception {
    // Add initial permission set
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSection = newAccessSectionInfo();

    PermissionInfo push = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    push.rules.put(SystemGroupBackend.PROJECT_OWNERS.get(), pri);
    accessSection.permissions.put(Permission.PUSH, push);

    PermissionInfo read = newPermissionInfo();
    pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    read.rules.put(SystemGroupBackend.ANONYMOUS_USERS.get(), pri);
    accessSection.permissions.put(Permission.READ, read);

    accessInput.add.put(REFS_ALL, accessSection);
    ProjectAccessInfo result = pApi.access(accessInput);
    assertThat(result.groups.keySet())
        .containsExactly(
            SystemGroupBackend.PROJECT_OWNERS.get(), SystemGroupBackend.ANONYMOUS_USERS.get());

    // Check the name, which is what the UI cares about; exhaustive
    // coverage of GroupInfo should be in groups REST API tests.
    assertThat(result.groups.get(SystemGroupBackend.PROJECT_OWNERS.get()).name)
        .isEqualTo("Project Owners");
    // Strip the ID, since it is in the key.
    assertThat(result.groups.get(SystemGroupBackend.PROJECT_OWNERS.get()).id).isNull();

    // Get call returns groups too.
    ProjectAccessInfo loggedInResult = pApi.access();
    assertThat(loggedInResult.groups.keySet())
        .containsExactly(
            SystemGroupBackend.PROJECT_OWNERS.get(), SystemGroupBackend.ANONYMOUS_USERS.get());
    assertThat(loggedInResult.groups.get(SystemGroupBackend.PROJECT_OWNERS.get()).name)
        .isEqualTo("Project Owners");
    assertThat(loggedInResult.groups.get(SystemGroupBackend.PROJECT_OWNERS.get()).id).isNull();

    // PROJECT_OWNERS is invisible to anonymous user, so we strip it.
    setApiUserAnonymous();
    ProjectAccessInfo anonResult = pApi.access();
    assertThat(anonResult.groups.keySet())
        .containsExactly(SystemGroupBackend.ANONYMOUS_USERS.get());
  }

  @Test
  public void updateParentAsUser() throws Exception {
    // Create child
    String newParentProjectName = createProject(PROJECT_NAME + "PA").get();

    // Set new parent
    ProjectAccessInput accessInput = newProjectAccessInput();
    accessInput.parent = newParentProjectName;

    setApiUser(user);
    exception.expect(AuthException.class);
    exception.expectMessage("administrate server not permitted");
    gApi.projects().name(newProjectName).access(accessInput);
  }

  @Test
  public void updateParentAsAdministrator() throws Exception {
    // Create parent
    String newParentProjectName = createProject(PROJECT_NAME + "PA").get();

    // Set new parent
    ProjectAccessInput accessInput = newProjectAccessInput();
    accessInput.parent = newParentProjectName;

    gApi.projects().name(newProjectName).access(accessInput);

    assertThat(pApi.access().inheritsFrom.name).isEqualTo(newParentProjectName);
  }

  @Test
  public void addGlobalCapabilityAsUser() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultGlobalCapabilitiesAccessSectionInfo();

    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

    setApiUser(user);
    exception.expect(AuthException.class);
    gApi.projects().name(allProjects.get()).access(accessInput);
  }

  @Test
  public void addGlobalCapabilityAsAdmin() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultGlobalCapabilitiesAccessSectionInfo();

    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

    ProjectAccessInfo updatedAccessSectionInfo =
        gApi.projects().name(allProjects.get()).access(accessInput);
    assertThat(
            updatedAccessSectionInfo
                .local
                .get(AccessSection.GLOBAL_CAPABILITIES)
                .permissions
                .keySet())
        .containsAllIn(accessSectionInfo.permissions.keySet());
  }

  @Test
  public void addGlobalCapabilityForNonRootProject() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultGlobalCapabilitiesAccessSectionInfo();

    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

    exception.expect(BadRequestException.class);
    pApi.access(accessInput);
  }

  @Test
  public void addNonGlobalCapabilityToGlobalCapabilities() throws Exception {
    InternalGroup adminGroup =
        groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null);

    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = newAccessSectionInfo();

    PermissionInfo permissionInfo = newPermissionInfo();
    permissionInfo.rules.put(adminGroup.getGroupUUID().get(), null);
    accessSectionInfo.permissions.put(Permission.PUSH, permissionInfo);

    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

    exception.expect(BadRequestException.class);
    gApi.projects().name(allProjects.get()).access(accessInput);
  }

  @Test
  public void removeGlobalCapabilityAsUser() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultGlobalCapabilitiesAccessSectionInfo();

    accessInput.remove.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

    setApiUser(user);
    exception.expect(AuthException.class);
    gApi.projects().name(allProjects.get()).access(accessInput);
  }

  @Test
  public void removeGlobalCapabilityAsAdmin() throws Exception {
    InternalGroup adminGroup =
        groupCache.get(new AccountGroup.NameKey("Administrators")).orElse(null);

    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = newAccessSectionInfo();

    PermissionInfo permissionInfo = newPermissionInfo();
    permissionInfo.rules.put(adminGroup.getGroupUUID().get(), null);
    accessSectionInfo.permissions.put(GlobalCapability.ACCESS_DATABASE, permissionInfo);

    // Add and validate first as removing existing privileges such as
    // administrateServer would break upcoming tests
    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

    ProjectAccessInfo updatedProjectAccessInfo =
        gApi.projects().name(allProjects.get()).access(accessInput);
    assertThat(
            updatedProjectAccessInfo
                .local
                .get(AccessSection.GLOBAL_CAPABILITIES)
                .permissions
                .keySet())
        .containsAllIn(accessSectionInfo.permissions.keySet());

    // Remove
    accessInput.add.clear();
    accessInput.remove.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

    updatedProjectAccessInfo = gApi.projects().name(allProjects.get()).access(accessInput);
    assertThat(
            updatedProjectAccessInfo
                .local
                .get(AccessSection.GLOBAL_CAPABILITIES)
                .permissions
                .keySet())
        .containsNoneIn(accessSectionInfo.permissions.keySet());
  }

  @Test
  public void unknownPermissionRemainsUnchanged() throws Exception {
    String access = "access";
    String unknownPermission = "unknownPermission";
    String registeredUsers = "group Registered Users";
    String refsFor = "refs/for/*";
    // Clone repository to forcefully add permission
    TestRepository<InMemoryRepository> allProjectsRepo = cloneProject(allProjects, admin);

    // Fetch permission ref
    GitUtil.fetch(allProjectsRepo, "refs/meta/config:cfg");
    allProjectsRepo.reset("cfg");

    // Load current permissions
    String config =
        gApi.projects()
            .name(allProjects.get())
            .branch(RefNames.REFS_CONFIG)
            .file(ProjectConfig.PROJECT_CONFIG)
            .asString();

    // Append and push unknown permission
    Config cfg = new Config();
    cfg.fromText(config);
    cfg.setString(access, refsFor, unknownPermission, registeredUsers);
    config = cfg.toText();
    PushOneCommit push =
        pushFactory.create(
            db, admin.getIdent(), allProjectsRepo, "Subject", ProjectConfig.PROJECT_CONFIG, config);
    push.to(RefNames.REFS_CONFIG).assertOkStatus();

    // Verify that unknownPermission is present
    config =
        gApi.projects()
            .name(allProjects.get())
            .branch(RefNames.REFS_CONFIG)
            .file(ProjectConfig.PROJECT_CONFIG)
            .asString();
    cfg.fromText(config);
    assertThat(cfg.getString(access, refsFor, unknownPermission)).isEqualTo(registeredUsers);

    // Make permission change through API
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();
    accessInput.add.put(refsFor, accessSectionInfo);
    gApi.projects().name(allProjects.get()).access(accessInput);
    accessInput.add.clear();
    accessInput.remove.put(refsFor, accessSectionInfo);
    gApi.projects().name(allProjects.get()).access(accessInput);

    // Verify that unknownPermission is still present
    config =
        gApi.projects()
            .name(allProjects.get())
            .branch(RefNames.REFS_CONFIG)
            .file(ProjectConfig.PROJECT_CONFIG)
            .asString();
    cfg.fromText(config);
    assertThat(cfg.getString(access, refsFor, unknownPermission)).isEqualTo(registeredUsers);
  }

  @Test
  public void updateGroupRefPermissions() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    accessInput.add.put(RefNames.REFS_GROUPS + "*", createDefaultAccessSectionInfo());
    exception.expect(BadRequestException.class);
    exception.expectMessage(
        "permissions on refs/groups/ are managed by gerrit and cannot be modified");
    gApi.projects().name(allProjects.get()).access(accessInput);
  }

  @Test
  public void updateGroupRefPermissionsAllowedOnCustomProject() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    accessInput.add.put(RefNames.REFS_GROUPS + "*", createDefaultAccessSectionInfo());
    gApi.projects().name(project.get()).access(accessInput);
  }

  @Test
  public void allUsersCanOnlyInheritFromAllProjects() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    accessInput.parent = project.get();
    exception.expect(BadRequestException.class);
    exception.expectMessage(allUsers.get() + " must inherit from " + allProjects.get());
    gApi.projects().name(allUsers.get()).access(accessInput);
  }

  @Test
  public void syncCreateGroupPermission() throws Exception {
    // Grant CREATE_GROUP to Registered Users
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSection = newAccessSectionInfo();
    PermissionInfo createGroup = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    createGroup.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    accessSection.permissions.put(GlobalCapability.CREATE_GROUP, createGroup);
    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSection);
    gApi.projects().name(allProjects.get()).access(accessInput);

    // Assert that the permission was synced from All-Projects (global) to All-Users (ref)
    Map<String, AccessSectionInfo> local = gApi.projects().name("All-Users").access().local;
    assertThat(local).isNotNull();
    assertThat(local).containsKey(RefNames.REFS_GROUPS + "*");
    Map<String, PermissionInfo> permissions = local.get(RefNames.REFS_GROUPS + "*").permissions;
    assertThat(permissions).containsKey(Permission.CREATE);
    Map<String, PermissionRuleInfo> rules = permissions.get(Permission.CREATE).rules;
    assertThat(rules.values()).containsExactly(pri);

    // Revoke the permission
    accessInput.add.clear();
    accessInput.remove.put(AccessSection.GLOBAL_CAPABILITIES, accessSection);
    gApi.projects().name(allProjects.get()).access(accessInput);

    // Assert that the permission was synced from All-Projects (global) to All-Users (ref)
    Map<String, AccessSectionInfo> local2 = gApi.projects().name("All-Users").access().local;
    assertThat(local2).isNotNull();
    assertThat(local2).doesNotContainKey(RefNames.REFS_GROUPS + "*");
  }

  private ProjectAccessInput newProjectAccessInput() {
    ProjectAccessInput p = new ProjectAccessInput();
    p.add = new HashMap<>();
    p.remove = new HashMap<>();
    return p;
  }

  private PermissionInfo newPermissionInfo() {
    PermissionInfo p = new PermissionInfo(null, null);
    p.rules = new HashMap<>();
    return p;
  }

  private AccessSectionInfo newAccessSectionInfo() {
    AccessSectionInfo a = new AccessSectionInfo();
    a.permissions = new HashMap<>();
    return a;
  }

  private AccessSectionInfo createDefaultAccessSectionInfo() {
    AccessSectionInfo accessSection = newAccessSectionInfo();

    PermissionInfo push = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    push.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    accessSection.permissions.put(Permission.PUSH, push);

    PermissionInfo codeReview = newPermissionInfo();
    codeReview.label = LABEL_CODE_REVIEW;
    pri = new PermissionRuleInfo(PermissionRuleInfo.Action.DENY, false);
    codeReview.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);

    pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    pri.max = 1;
    pri.min = -1;
    codeReview.rules.put(SystemGroupBackend.PROJECT_OWNERS.get(), pri);
    accessSection.permissions.put(Permission.LABEL + LABEL_CODE_REVIEW, codeReview);

    return accessSection;
  }

  private AccessSectionInfo createDefaultGlobalCapabilitiesAccessSectionInfo() {
    AccessSectionInfo accessSection = newAccessSectionInfo();

    PermissionInfo email = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    email.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    accessSection.permissions.put(GlobalCapability.EMAIL_REVIEWERS, email);

    return accessSection;
  }

  private AccessSectionInfo createAccessSectionInfoDenyAll() {
    AccessSectionInfo accessSection = newAccessSectionInfo();

    PermissionInfo read = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.DENY, false);
    read.rules.put(SystemGroupBackend.ANONYMOUS_USERS.get(), pri);
    accessSection.permissions.put(Permission.READ, read);

    return accessSection;
  }
}


text:
FROM ubuntu:14.04

RUN apt-get update && apt-get install -y wget

RUN mkdir -p /data/lucid_prod /data/local /logs /mongodb
RUN wget --no-check-certificate --progress=dot:mega -O - https://s3-us-west-1.amazonaws.com/relateiq-build-resources/mongodb-linux-x86_64-3.0.2.tgz | tar -zx -C /mongodb --strip-components=1

EXPOSE 27017 28017

ADD mongo.conf /mongo.conf
ADD rs-initiate.sh /rs-initiate.sh
RUN /rs-initiate.sh

CMD ["/mongodb/bin/mongod", "-f", "/mongo.conf"]


text:
openshift_clam_update
=========

Ansible role for creating and configuring a ClamAV Signature Updater container

Requirements
------------

Ansible Modules:

- tools_roles/lib_openshift_3.2

Role Variables
--------------

- `ocav_namespace`: The project namespace to which the application should be deployed.
- `ocav_pods_running`: A list of running pods in the project.
- `ocav_zagg_config`: A dictionary with config data for the ZAGG monitoring client, to populate `zagg_client.yaml`. Expected values: `hostgroups`, `url`, `user`, `password`, `ssl_verify`, `verbose` and `debug`. The value `ocav_zagg_config.hostgroups` should be a list of host group names.

Dependencies
------------

Example Playbook
----------------

License
-------

Apache 2.0

Author Information
------------------

Openshift Operations


text:
package org.b3log.solo.processor;

import java.io.PrintWriter;
import java.io.StringWriter;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.b3log.latke.model.User;
import org.b3log.solo.AbstractTestCase;
import org.b3log.solo.service.InitService;
import org.b3log.solo.service.UserQueryService;
import org.json.JSONObject;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.testng.Assert;
import org.testng.annotations.Test;

/**
 * {@link SitemapProcessor} test case.
 *
 * @author Liang Ding
 * @version 1.0.0.0, Nov 5, 2016
 * @since 1.7.0
 */
@Test(suiteName = "processor")
public class SitemapProcessorTestCase extends AbstractTestCase {

    /**
     * Init.
     *
     * @throws Exception exception
     */
    @Test
    public void init() throws Exception {
        final InitService initService = getInitService();

        final JSONObject requestJSONObject = new JSONObject();
        requestJSONObject.put(User.USER_EMAIL, "test@gmail.com");
        requestJSONObject.put(User.USER_NAME, "Admin");
        requestJSONObject.put(User.USER_PASSWORD, "pass");

        initService.init(requestJSONObject);

        final UserQueryService userQueryService = getUserQueryService();
        Assert.assertNotNull(userQueryService.getUserByEmail("test@gmail.com"));
    }

    /**
     * blogArticlesAtom.
     *
     * @throws Exception exception
     */
    @Test(dependsOnMethods = "init")
    public void blogArticlesAtom() throws Exception {
        final HttpServletRequest request = mock(HttpServletRequest.class);
        when(request.getServletContext()).thenReturn(mock(ServletContext.class));
        when(request.getRequestURI()).thenReturn("/sitemap.xml");
        when(request.getMethod()).thenReturn("GET");

        final MockDispatcherServlet dispatcherServlet = new MockDispatcherServlet();
        dispatcherServlet.init();

        final StringWriter stringWriter = new StringWriter();
        final PrintWriter printWriter = new PrintWriter(stringWriter);

        final HttpServletResponse response = mock(HttpServletResponse.class);
        when(response.getWriter()).thenReturn(printWriter);

        dispatcherServlet.service(request, response);

        final String content = stringWriter.toString();
        Assert.assertTrue(StringUtils.startsWith(content, "<?xml version=\"1.0\""));
    }
}


text:
class Apps::SyncJob < ApplicationJob
  queue_as :default

  def perform(app_id)
    app = App.find(app_id) rescue return

    app.syncing!

  end
end


text:
@interface NBPhoneMetadataNU : NBPhoneMetaData
{
}

- (id)init;

@end


text:
#ifndef DateTimeLocalInputType_h
#define DateTimeLocalInputType_h

#if ENABLE(INPUT_TYPE_DATETIMELOCAL)
#include "BaseMultipleFieldsDateAndTimeInputType.h"

namespace WebCore {

#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
typedef BaseMultipleFieldsDateAndTimeInputType BaseDateTimeLocalInputType;
#else
typedef BaseDateAndTimeInputType BaseDateTimeLocalInputType;
#endif

class DateTimeLocalInputType : public BaseDateTimeLocalInputType {
public:
    static PassOwnPtr<InputType> create(HTMLInputElement*);

private:
    DateTimeLocalInputType(HTMLInputElement* element) : BaseDateTimeLocalInputType(element) { }
    virtual const AtomicString& formControlType() const OVERRIDE;
    virtual DateComponents::Type dateType() const OVERRIDE;
    virtual double valueAsDate() const OVERRIDE;
    virtual void setValueAsDate(double, ExceptionCode&) const OVERRIDE;
    virtual StepRange createStepRange(AnyStepHandling) const;
    virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const OVERRIDE;
    virtual bool setMillisecondToDateComponents(double, DateComponents*) const OVERRIDE;
    virtual bool isDateTimeLocalField() const OVERRIDE;

#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
    // BaseMultipleFieldsDateAndTimeInputType functions
    virtual String formatDateTimeFieldsState(const DateTimeFieldsState&) const OVERRIDE FINAL;
    virtual void setupLayoutParameters(DateTimeEditElement::LayoutParameters&, const DateComponents&) const OVERRIDE FINAL;
#endif
};

} // namespace WebCore

#endif
#endif // DateTimeLocalInputType_h


text:
// Package disksort implements sorting algorithms for sets of data too large to
// fit fully in-memory.  If the number of elements becomes to large, data are
// paged onto the disk.
package disksort

import (
	"bufio"
	"container/heap"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"kythe.io/kythe/go/platform/delimited"
	"kythe.io/kythe/go/util/sortutil"

	"github.com/golang/snappy"
)

// Interface is the standard interface for disk sorting algorithms.  Each
// element in the set of data to be sorted is added to the sorter with Add.
// Once all elements are added, Read can then be called to retrieve each element
// sequentially in sorted order.  Once Read is called, no other operations on
// the sorter are allowed.
type Interface interface {
	// Add adds a new element to the set of data to be sorted.
	Add(i interface{}) error

	// Iterator returns an Iterator to read each of the elements previously added
	// to the set of data to be sorted.  Once Iterator is called, no more data may
	// be added to the sorter.  This is a lower-level version of Read.  Iterator
	// and Read may only be called once.
	Iterator() (Iterator, error)

	// Read calls f on each elements previously added the set of data to be
	// sorted.  If f returns an error, it is returned immediately and f is no
	// longer called.  Once Read is called, no more data may be added to the
	// sorter.  Iterator and Read may only be called once.
	Read(f func(interface{}) error) error
}

// An Iterator reads each element, in order, in a sorted dataset.
type Iterator interface {
	// Next returns the next ordered element.  If none exist, an io.EOF error is
	// returned.
	Next() (interface{}, error)

	// Close releases all of the Iterator's used resources.  Each Iterator must be
	// closed after the client's last call to Next or stray temporary files may be
	// left on disk.
	Close() error
}

// Marshaler is an interface to functions that can binary encode/decode
// elements.
type Marshaler interface {
	// Marshal binary encodes the given element.
	Marshal(interface{}) ([]byte, error)

	// Unmarshal decodes the given encoding of an element.
	Unmarshal([]byte) (interface{}, error)
}

type mergeSorter struct {
	opts MergeOptions

	buffer  []interface{}
	workDir string
	shards  []string

	finalized bool
}

// DefaultMaxInMemory is the default number of elements to keep in-memory during
// a merge sort.
const DefaultMaxInMemory = 32000

// DefaultIOBufferSize is the default size of the reading/writing buffers for
// the temporary file shards.
const DefaultIOBufferSize = 2 << 13

// MergeOptions specifies how to sort elements.
type MergeOptions struct {
	// Lesser is the comparison function for sorting the given elements.
	Lesser sortutil.Lesser
	// Marshaler is used for encoding/decoding elements in temporary file shards.
	Marshaler Marshaler

	// WorkDir is the directory used for writing temporary file shards.  If empty,
	// the default directory for temporary files is used.
	WorkDir string

	// MaxInMemory is the maximum number of elements to keep in-memory before
	// paging them to a temporary file shard.  If non-positive, DefaultMaxInMemory
	// is used.
	MaxInMemory int

	// CompressShards determines whether the temporary file shards should be
	// compressed.
	CompressShards bool

	// IOBufferSize is the size of the reading/writing buffers for the temporary
	// file shards.  If non-positive, DefaultIOBufferSize is used.
	IOBufferSize int
}

// NewMergeSorter returns a new disk sorter using a mergesort algorithm.
func NewMergeSorter(opts MergeOptions) (Interface, error) {
	if opts.Lesser == nil {
		return nil, errors.New("missing Lesser")
	} else if opts.Marshaler == nil {
		return nil, errors.New("missing Marshaler")
	}

	dir, err := ioutil.TempDir(opts.WorkDir, "external.merge.sort")
	if err != nil {
		return nil, fmt.Errorf("error creating temporary work directory: %v", err)
	}

	if opts.MaxInMemory <= 0 {
		opts.MaxInMemory = DefaultMaxInMemory
	}
	if opts.IOBufferSize <= 0 {
		opts.IOBufferSize = DefaultIOBufferSize
	}

	return &mergeSorter{
		opts:    opts,
		buffer:  make([]interface{}, 0, opts.MaxInMemory),
		workDir: dir,
	}, nil
}

var (
	// ErrAlreadyFinalized is returned from Interface#Add and Interface#Read when
	// Interface#Read has already been called, freezing the sort's inputs/outputs.
	ErrAlreadyFinalized = errors.New("sorter already finalized")
)

// Add implements part of the Interface interface.
func (m *mergeSorter) Add(i interface{}) error {
	if m.finalized {
		return ErrAlreadyFinalized
	}

	m.buffer = append(m.buffer, i)
	if len(m.buffer) >= m.opts.MaxInMemory {
		return m.dumpShard()
	}
	return nil
}

type mergeIterator struct {
	buffer []interface{}

	merger    *sortutil.ByLesser
	marshaler Marshaler
	workDir   string
}

// Iterator implements part of the Interface interface.
func (m *mergeSorter) Iterator() (iter Iterator, err error) {
	if m.finalized {
		return nil, ErrAlreadyFinalized
	}
	m.finalized = true // signal that further operations should fail

	it := &mergeIterator{workDir: m.workDir, marshaler: m.opts.Marshaler}

	if len(m.shards) == 0 {
		// Fast path for a single, in-memory shard
		it.buffer, m.buffer = m.buffer, nil
		sortutil.Sort(m.opts.Lesser, it.buffer)
		return it, nil
	}

	// This is a heap storing the head of each shard.
	merger := &sortutil.ByLesser{
		Lesser: &mergeElementLesser{Lesser: m.opts.Lesser},
	}
	it.merger = merger

	defer func() {
		// Try to cleanup on errors
		if err != nil {
			if cErr := it.Close(); cErr != nil {
				log.Printf("WARNING: error closing Iterator after error: %v", cErr)
			}
		}
	}()

	if len(m.buffer) != 0 {
		// To make the merging algorithm simpler, dump the last shard to disk.
		if err := m.dumpShard(); err != nil {
			m.buffer = nil
			return nil, fmt.Errorf("error dumping final shard: %v", err)
		}
	}
	m.buffer = nil

	// Initialize the merger heap by reading the first element of each shard.
	for _, shard := range m.shards {
		f, err := os.OpenFile(shard, os.O_RDONLY, shardFileMode)
		if err != nil {
			return nil, fmt.Errorf("error opening shard %q: %v", shard, err)
		}

		r := io.Reader(f)
		if m.opts.CompressShards {
			r = snappy.NewReader(r)
		}

		rd := delimited.NewReader(bufio.NewReaderSize(r, m.opts.IOBufferSize))
		first, err := rd.Next()
		if err != nil {
			f.Close()
			return nil, fmt.Errorf("error reading beginning of shard %q: %v", shard, err)
		}
		el, err := m.opts.Marshaler.Unmarshal(first)
		if err != nil {
			f.Close()
			return nil, fmt.Errorf("error unmarshaling beginning of shard %q: %v", shard, err)
		}

		heap.Push(merger, &mergeElement{el: el, rd: rd, f: f})
	}

	return it, nil
}

// Next implements part of the Iterator interface.
func (i *mergeIterator) Next() (interface{}, error) {
	if i.merger == nil {
		// Fast path for a single, in-memory shard
		if len(i.buffer) == 0 {
			return nil, io.EOF
		}
		val := i.buffer[0]
		i.buffer = i.buffer[1:]
		return val, nil
	}

	if i.merger.Len() == 0 {
		return nil, io.EOF
	}

	// While the merger heap is non-empty:
	//   el := pop the head of the heap
	//   pass it to the user-specific function
	//   push the next element el.rd to the merger heap
	x := heap.Pop(i.merger).(*mergeElement)
	el := x.el

	// Read and parse the next value on the same shard
	rec, err := x.rd.Next()
	if err != nil {
		_ = x.f.Close()           // ignore errors (file is only open for reading)
		_ = os.Remove(x.f.Name()) // ignore errors (os.RemoveAll used in Close)
		if err != io.EOF {
			return nil, fmt.Errorf("error reading shard: %v", err)
		}
	} else {
		next, err := i.marshaler.Unmarshal(rec)
		if err != nil {
			return nil, fmt.Errorf("error unmarshaling element: %v", err)
		}

		// Reuse mergeElement, push it back onto the merger heap with the next value
		x.el = next
		heap.Push(i.merger, x)
	}

	return el, nil
}

// Close implements part of the Iterator interface.
func (i *mergeIterator) Close() error {
	i.buffer = nil
	if i.merger != nil {
		for i.merger.Len() != 0 {
			x := heap.Pop(i.merger).(*mergeElement)
			_ = x.f.Close() // ignore errors (file is only open for reading)
		}
	}
	if rmErr := os.RemoveAll(i.workDir); rmErr != nil {
		return fmt.Errorf("error removing temporary directory %q: %v", i.workDir, rmErr)
	}
	return nil
}

// Read implements part of the Interface interface.
func (m *mergeSorter) Read(f func(i interface{}) error) (err error) {
	it, err := m.Iterator()
	if err != nil {
		return err
	}
	defer func() {
		if cErr := it.Close(); cErr != nil {
			if err == nil {
				err = cErr
			} else {
				log.Println("WARNING: error closing Iterator:", cErr)
			}
		}
	}()
	for {
		val, err := it.Next()
		if err == io.EOF {
			return nil
		} else if err != nil {
			return err
		}
		if err := f(val); err != nil {
			return err
		}
	}
}

const shardFileMode = 0600 | os.ModeExclusive | os.ModeAppend | os.ModeTemporary | os.ModeSticky

func (m *mergeSorter) dumpShard() (err error) {
	defer func() {
		m.buffer = make([]interface{}, 0, m.opts.MaxInMemory)
	}()

	// Create a new shard file
	shardPath := filepath.Join(m.workDir, fmt.Sprintf("shard.%.6d", len(m.shards)))
	file, err := os.OpenFile(shardPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, shardFileMode)
	if err != nil {
		return fmt.Errorf("error creating shard: %v", err)
	}
	defer func() {
		replaceErrIfNil(&err, "error closing shard: %v", file.Close())
	}()

	w := io.Writer(file)
	if m.opts.CompressShards {
		w = snappy.NewWriter(w)
	}

	// Buffer writing to the shard
	buf := bufio.NewWriterSize(w, m.opts.IOBufferSize)
	defer func() {
		replaceErrIfNil(&err, "error flushing shard: %v", buf.Flush())
	}()

	// Sort the in-memory buffer of elements
	sortutil.Sort(m.opts.Lesser, m.buffer)

	// Write each element of the in-memory to shard file, in sorted order
	wr := delimited.NewWriter(buf)
	for len(m.buffer) > 0 {
		rec, err := m.opts.Marshaler.Marshal(m.buffer[0])
		if err != nil {
			return fmt.Errorf("marshaling error: %v", err)
		}
		if _, err := wr.Write(rec); err != nil {
			return fmt.Errorf("writing error: %v", err)
		}
		m.buffer = m.buffer[1:]
	}

	m.shards = append(m.shards, shardPath)
	return nil
}

func replaceErrIfNil(err *error, s string, newError error) {
	if newError != nil && *err == nil {
		*err = fmt.Errorf(s, newError)
	}
}

type mergeElement struct {
	el interface{}
	rd delimited.Reader
	f  *os.File
}

type mergeElementLesser struct{ sortutil.Lesser }

// Less implements the sortutil.Lesser interface.
func (m *mergeElementLesser) Less(a, b interface{}) bool {
	x, y := a.(*mergeElement), b.(*mergeElement)
	return m.Lesser.Less(x.el, y.el)
}


text:
package com.ksa.dao.logistics.mybatis;

import java.util.HashMap;
import java.util.Map;

import org.springframework.util.StringUtils;

import com.ksa.dao.AbstractMybatisDao;
import com.ksa.dao.logistics.BookingNoteDao;
import com.ksa.model.logistics.BookingNote;
import com.ksa.model.logistics.BookingNoteState;

/**
 * 基于 Mybaits 的 BookingNoteDao 实现。
 *
 * @author 麻文强
 *
 * @since v0.0.1
 */
public class MybatisBookingNoteDao extends AbstractMybatisDao implements BookingNoteDao {

    @Override
    public int insertBookingNote( BookingNote note ) throws RuntimeException {
        return this.session.insert( "insert-logistics-bookingnote", note );
    }

    @Override
    public int updateBookingNote( BookingNote note ) throws RuntimeException {
        return this.session.update( "update-logistics-bookingnote", note );
    }

    @Override
    public int updateBookingNoteState( BookingNote note ) throws RuntimeException {
        return this.session.update( "update-logistics-bookingnote-state", note );
    }

    @Override
    public int updateBookingNoteType( BookingNote note ) throws RuntimeException {
      return this.session.update( "update-logistics-bookingnote-type", note );
    }

    @Override
    public int updateBookingNoteChargeDate( BookingNote note ) throws RuntimeException {
        return this.session.update( "update-logistics-bookingnote-chargedate", note );
    }

    @Override
    public int deleteBookingNote( BookingNote note ) throws RuntimeException {
        note.setState( BookingNoteState.DELETED );  // 将托单的状态设置为 '已删除'
        return updateBookingNoteState( note );
    }

    @Override
    public BookingNote selectBookingNoteById( String id ) throws RuntimeException {
        return this.session.selectOne( "select-logistics-bookingnote-byid", id );
    }

    @Override
    public int selectBookingNoteCount() throws RuntimeException {
        return ( (Integer) this.session.selectOne( "count-logistics-bookingnote" ) ).intValue();
    }

    @Override
    public int selectBookingNoteCount( String queryString ) throws RuntimeException {
        Map<String, Object> para = new HashMap<String, Object>();
        // FIXME 对应sql中参数名是 queryClauses,这个参数设置无用!只能查到全部数据!
        para.put( "queryClause", new String[]{ queryString } );
        return ( (Integer) this.session.selectOne( "count-logistics-bookingnote-query", para ) ).intValue();
    }

    @Override
    public BookingNote selectBookingNoteByLading( BookingNote note ) throws RuntimeException {
        if( !StringUtils.hasText( note.getHawb() ) && !StringUtils.hasText( note.getMawb() ) ) {
            throw new IllegalArgumentException( "通过提单号查询托单时,主副提单号不能同时为空。" );
        }
        BookingNote param = new BookingNote();
        param.setId( note.getId() );
        if( StringUtils.hasText( note.getMawb() ) ) {
            param.setMawb( note.getMawb() );
        }
        if( StringUtils.hasText( note.getHawb() ) ) {
            param.setHawb( note.getHawb() );
        }
        return this.session.selectOne( "select-logistics-bookingnote-bylading", param );
    }
}


text:
<template name="Update_Student_Widget">

UPDATE STUDENT

    <form class="ui equal width form {{successClass}} {{errorClass}} {{#if hasNewLevel}}warning{{/if}}">

        {{> Input_Form_Field label="Username" name="username" value=user.username errorMessage=(fieldError "username") disabled=true}}
        {{> Input_Form_Field label="Role" name="role" value=selectedRole errorMessage=(fieldError "role") disabled=true}}

        {{> Input_Form_Field label="First" name="firstName" value=user.firstName errorMessage=(fieldError "firstName") required=true}}
        {{> Input_Form_Field label="Last" name="lastName" value=user.lastName errorMessage=(fieldError "lastName") required=true}}

Optional fields (all users)

        {{> Picture_Form_Field label="Picture" name="picture" value=user.picture errorMessage=(fieldError "picture") }}
        {{> Input_Form_Field label="Website" name="website" value=user.website errorMessage=(fieldError "website") }}

        {{> Career_Goals_Form_Field careerGoals=careerGoals selectedCareerGoalIDs=selectedCareerGoalIDs errorMessage=(fieldError "careerGoals")}}
        {{> Interests_Form_Field interests=interests selectedInterestIDs=selectedInterestIDs errorMessage=(fieldError
            "interests")}}

        {{> Boolean_Form_Field label='Is Alumni' name='isAlumni' trueValue=trueValueAlumni falseValue=falseValueAlumni errorMessage=(fieldError "isAlumni") required=true}}
        {{> Input_Form_Field label="Level" name="level" value=calcLevel errorMessage=(fieldError "level") type="Number" disabled=true}}

        {{> Semesters_Single_Form_Field selectedSemesterID=selectedSemesterID semesters=semesters errorMessage=(fieldError "semesters") name="declaredSemester" label="Declared Semester"}}
        {{> Academic_Plan_Form_Field plans=plans selectedPlan=selectedPlan}}

      {{#if hasNewLevel}}

New Level!!

      {{/if}}
      <button class="ui green basic button" type="submit">Update</button>
      <button class="ui green basic button jsCancel" type="submit">Cancel</button>
      {{> Success_Message_Form_Field message="The User was successfully updated.  Press cancel to continue."}}
    </form>
    {{#if slug}}

View {{user.firstName}}'s degree plan: /student/{{slug}}
        /degree-planner

    {{/if}}

</template>


text:
"""Extension of flask.Response.
"""

from flask import Response as ResponseBase, json, current_app, request

class Response(ResponseBase):
    """Extend flask.Response with support for list/dict conversion to JSON."""
    def __init__(self, content=None, *args, **kargs):
        if isinstance(content, (list, dict)):
            kargs['mimetype'] = 'application/json'
            content = to_json(content)

        super(Response, self).__init__(content, *args, **kargs)

    @classmethod
    def force_type(cls, response, environ=None):
        """Override with support for list/dict."""
        if isinstance(response, (list, dict)):
            return cls(response)
        else:
            return super(Response, cls).force_type(response, environ)

def to_json(content):
    """Converts content to json while respecting config options."""
    indent = None
    separators = (',', ':')

    if (current_app.config['JSONIFY_PRETTYPRINT_REGULAR']
            and not request.is_xhr):
        indent = 2
        separators = (', ', ': ')

    return (json.dumps(content, indent=indent, separators=separators), '\n')