text:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Contains code for a ray collider.
 *	\file		OPC_RayCollider.cpp
 *	\author		Pierre Terdiman
 *	\date		June, 2, 2001
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Contains a ray-vs-tree collider.
 *	This class performs a stabbing query on an AABB tree, i.e. does a ray-mesh collision.
 *
 *	HIGHER DISTANCE BOUND:
 *
 *		If P0 and P1 are two 3D points, let's define:
 *		- d = distance between P0 and P1
 *		- Origin	= P0
 *		- Direction	= (P1 - P0) / d = normalized direction vector3
 *		- A parameter t such as a point P on the line (P0,P1) is P = Origin + t * Direction
 *		- t = 0  -->  P = P0
 *		- t = d  -->  P = P1
 *
 *		Then we can define a general "ray" as:
 *
 *			struct Ray
 *			{
 *				Point	Origin;
 *				Point	Direction;
 *			};
 *
 *		But it actually maps three different things:
 *		- a segment,   when 0 <= t <= d
 *		- a half-line, when 0 <= t < +infinity, or -infinity < t <= d
 *		- a line,      when -infinity < t < +infinity
 *
 *		In Opcode, we support segment queries, which yield half-line queries by setting d = +infinity.
 *		We don't support line-queries. If you need them, shift the origin along the ray by an appropriate margin.
 *
 *		In short, the lower bound is always 0, and you can setup the higher bound "d" with RayCollider::SetMaxDist().
 *
 *		Query	|segment			|half-line		|line
 *		--------|-------------------|---------------|----------------
 *		Usages	|-shadow feelers	|-raytracing	|-
 *				|-sweep tests		|-in/out tests	|
 *
 *	FIRST CONTACT:
 *
 *		- You can setup "first contact" mode or "all contacts" mode with RayCollider::SetFirstContact().
 *		- In "first contact" mode we return as soon as the ray hits one face. If can be useful e.g. for shadow feelers, where
 *		you want to know whether the path to the light is _free or not (a boolean answer is enough).
 *		- In "all contacts" mode we return all faces hit by the ray.
 *
 *	TEMPORAL COHERENCE:
 *
 *		- You can enable or disable temporal coherence with RayCollider::SetTemporalCoherence().
 *		- It currently only works in "first contact" mode.
 *		- If temporal coherence is enabled, the previously hit triangle is cached during the first query. Then, next queries
 *		start by colliding the ray against the cached triangle. If they still collide, we return immediately.
 *
 *	CLOSEST HIT:
 *
 *		- You can enable or disable "closest hit" with RayCollider::SetClosestHit().
 *		- It currently only works in "all contacts" mode.
 *		- If closest hit is enabled, faces are sorted by distance on-the-fly and the closest one only is reported.
 *
 *	BACKFACE CULLING:
 *
 *		- You can enable or disable backface culling with RayCollider::SetCulling().
 *		- If culling is enabled, ray will not hit back faces (only front faces).
 *
 *
 *
 *	\class		RayCollider
 *	\author		Pierre Terdiman
 *	\version	1.2
 *	\date		June, 2, 2001
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Precompiled Header
#include "stdafx.h"
#pragma hdrstop

using namespace Opcode;

#include "OPC_RayAABBOverlap.h"
#include "OPC_RayTriOverlap.h"

#define HANDLE_CONTACT(prim)																	\
	/* Set contact status */																	\
	mFlags |= OPC_CONTACT;																		\
																								\
	if(mStabbedFaces)																			\
	{																							\
		if(!mClosestHit || !mStabbedFaces->GetNbFaces())										\
		{																						\
			mStabbedFace.mFaceID = prim;														\
			mStabbedFaces->AddFace(mStabbedFace);												\
		}																						\
		else																					\
		{																						\
			CollisionFace* Current = const_cast<CollisionFace*>(mStabbedFaces->GetFaces());		\
			if(Current && mStabbedFace.mDistance<Current->mDistance)							\
			{																					\
				mStabbedFace.mFaceID = prim;													\
				*Current = mStabbedFace;														\
			}																					\
		}																						\
	}

#ifdef OPC_USE_CALLBACKS
	#define STAB_PRIM(prim)																		\
		/* Request vertices from the app */														\
		VertexPointers VP;	(mObjCallback)(prim, VP, mUserData);								\
																								\
		/* Perform ray-tri overlap test and return */											\
		if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))							\
		{																						\
			/* Intersection point is valid if: */												\
			/* - distance is positive (else it can just be a face behind the orig point) */		\
			/* - distance is smaller than a given max distance (useful for shadow feelers) */	\
			if(!IS_NEGATIVE_FLOAT(mStabbedFace.mDistance))										\
			{																					\
				mNbIntersections++;																\
				if(IR(mStabbedFace.mDistance)<IR(mMaxDist))										\
				{																				\
					HANDLE_CONTACT(prim)														\
				}																				\
			}																					\
		}
#else
	#define STAB_PRIM(prim)																		\
		const IndexedTriangle* Tri = &mFaces[prim];												\
																								\
		/* Perform ray-tri overlap test and return */											\
		if(RayTriOverlap(mVerts[Tri->mVRef[0]], mVerts[Tri->mVRef[1]], mVerts[Tri->mVRef[2]]))	\
		{																						\
			/* Intersection point is valid if: */												\
			/* - distance is positive (else it can just be a face behind the orig point) */		\
			/* - distance is smaller than a given max distance (useful for shadow feelers) */	\
			if(!IS_NEGATIVE_FLOAT(mStabbedFace.mDistance))										\
			{																					\
				mNbIntersections++;																\
				if(IR(mStabbedFace.mDistance)<IR(mMaxDist))										\
				{																				\
					HANDLE_CONTACT(prim)														\
				}																				\
			}																					\
		}
#endif

#ifdef OPC_USE_CALLBACKS
	#define UNBOUNDED_STAB_PRIM(prim)															\
		/* Request vertices from the app */														\
		VertexPointers VP;	(mObjCallback)(prim, VP, mUserData);								\
																								\
		/* Perform ray-tri overlap test and return */											\
		if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))							\
		{																						\
			/* Intersection point is valid if: */												\
			/* - distance is positive (else it can just be a face behind the orig point) */		\
			if(!IS_NEGATIVE_FLOAT(mStabbedFace.mDistance))										\
			{																					\
				mNbIntersections++;																\
				HANDLE_CONTACT(prim)															\
			}																					\
		}
#else
	#define UNBOUNDED_STAB_PRIM(prim)															\
		const IndexedTriangle* Tri = &mFaces[prim];												\
																								\
		/* Perform ray-tri overlap test and return */											\
		if(RayTriOverlap(mVerts[Tri->mVRef[0]], mVerts[Tri->mVRef[1]], mVerts[Tri->mVRef[2]]))	\
		{																						\
			/* Intersection point is valid if: */												\
			/* - distance is positive (else it can just be a face behind the orig point) */		\
			if(!IS_NEGATIVE_FLOAT(mStabbedFace.mDistance))										\
			{																					\
				mNbIntersections++;																\
				HANDLE_CONTACT(prim)															\
			}																					\
		}
#endif

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Constructor.
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RayCollider::RayCollider()
 :	mNbRayBVTests		(0),
	mNbRayPrimTests		(0),
	mNbIntersections	(0),
	mClosestHit			(false),
	mCulling			(true),
#ifdef OPC_USE_CALLBACKS
	mUserData			(0),
	mObjCallback		(null),
#else
	mFaces				(null),
	mVerts				(null),
#endif
	mStabbedFaces		(null),
	mMaxDist			(flt_max)
{
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Destructor.
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RayCollider::~RayCollider()
{
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Validates current settings. You should call this method after all the settings and callbacks have been defined.
 *	\return		null if everything is ok, else a string describing the problem
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const char* RayCollider::ValidateSettings()
{
#ifdef OPC_USE_CALLBACKS
	if(!mObjCallback)											return "Object callback must be defined! Call: SetCallback().";
#else
	if(!mFaces || !mVerts)										return "Object pointers must be defined! Call: SetPointers().";
#endif
	if(mMaxDist<0.0f)											return "Higher distance bound must be positive!";
	if(TemporalCoherenceEnabled() && !FirstContactEnabled())	return "Temporal coherence only works with ""First contact"" mode!";
	if(mClosestHit && FirstContactEnabled())					return "Closest hit doesn't work with ""First contact"" mode!";
	return null;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Generic stabbing query for generic OPCODE models. After the call, access the results:
 *	- with GetContactStatus()
 *	- in the user-provided destination array
 *
 *	\param		world_ray		[in] stabbing ray in world space
 *	\param		model			[in] Opcode model to collide with
 *	\param		world			[in] model's world matrix, or null
 *	\param		cache			[in] a possibly cached face index, or null
 *	\return		true if success
 *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool RayCollider::Collide(const Ray& world_ray, OPCODE_Model* model, const Matrix4x4* world, udword* cache)
{
	// Checkings
	if(!model)	return false;

	// Simple double-dispatch
	if(!model->HasLeafNodes())
	{
		if(model->IsQuantized())	return Collide(world_ray, (const AABBQuantizedNoLeafTree*)model->GetTree(), world, cache);
		else						return Collide(world_ray, (const AABBNoLeafTree*)model->GetTree(), world, cache);
	}
	else
	{
		if(model->IsQuantized())	return Collide(world_ray, (const AABBQuantizedTree*)model->GetTree(), world, cache);
		else						return Collide(world_ray, (const AABBCollisionTree*)model->GetTree(), world, cache);
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Initializes a stabbing query :
 *	- reset stats & contact status
 *	- compute ray in local space
 *	- check temporal coherence
 *
 *	\param		world_ray		[in] stabbing ray in world space
 *	\param		world			[in] object's world matrix, or null
 *	\param		faceid		[in] index of previously stabbed triangle
 *	\return		contact status
 *	\warning	SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only.
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL RayCollider::InitQuery(const Ray& world_ray, const Matrix4x4* world, udword* faceid)
{
	// Reset stats & contact status
	Collider::InitQueryEx();
	mNbRayBVTests		= 0;
	mNbRayPrimTests		= 0;
	mNbIntersections	= 0;
	if(mStabbedFaces)	mStabbedFaces->Reset();

	// Compute ray in local space
	// The (Origin/Dir) form is needed for the ray-triangle test anyway
	if(world)
	{
		Matrix3x3 InvWorld = *world;
		mDir = InvWorld * world_ray.mDir;

		Matrix4x4 World;
		InvertPRMatrix(World, *world);
		mOrigin = world_ray.mOrig * World;
	}
	else
	{
		mDir	= world_ray.mDir;
		mOrigin	= world_ray.mOrig;
	}

	// Precompute data
	if(IR(mMaxDist)!=IEEE_MAX_FLOAT)
	{
		// For Segment-AABB overlap
		mData = 0.5f * mDir * mMaxDist;
		mData2 = mOrigin + mData;

		// Precompute mFDir;
		mFDir.x = _abs(mData.x);
		mFDir.y = _abs(mData.y);
		mFDir.z = _abs(mData.z);
	}
	else
	{
		// For Ray-AABB overlap
//		udword x = SIR(mDir.x)-1;
//		udword y = SIR(mDir.y)-1;
//		udword z = SIR(mDir.z)-1;
//		mData.x = FR(x);
//		mData.y = FR(y);
//		mData.z = FR(z);

		// Precompute mFDir;
		mFDir.x = _abs(mDir.x);
		mFDir.y = _abs(mDir.y);
		mFDir.z = _abs(mDir.z);
	}

	// Check temporal coherence :

//## voir mClosest

	// Test previously colliding primitives first
	if(TemporalCoherenceEnabled() && FirstContactEnabled() && faceid && *faceid!=INVALID_ID)
	{
		// Request vertices from the app
		VertexPointers VP;
#ifdef OPC_USE_CALLBACKS
		(mObjCallback)(*faceid, VP, mUserData);
#else
		const IndexedTriangle* Tri = &mFaces[*faceid];
		VP.Vertex[0] = &mVerts[Tri->mVRef[0]];
		VP.Vertex[1] = &mVerts[Tri->mVRef[1]];
		VP.Vertex[2] = &mVerts[Tri->mVRef[2]];
#endif
		// Perform ray-cached tri overlap
		if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))
		{
			// Intersection point is valid if:
			// - distance is positive (else it can just be a face behind the orig point)
			// - distance is smaller than a given max distance (useful for shadow feelers)
			if(mStabbedFace.mDistance>0.0f && mStabbedFace.mDistance<mMaxDist)
			{
				// Set contact status
				mFlags |= OPC_CONTACT;

				mStabbedFace.mFaceID = *faceid;

				if(mStabbedFaces)	mStabbedFaces->AddFace(mStabbedFace);
			}
		}
	}
	return GetContactStatus();
}

#define UPDATE_CACHE												\
	if(cache && GetContactStatus() && mStabbedFaces)				\
	{																\
		const CollisionFace* Current = mStabbedFaces->GetFaces();	\
		if(Current)	*cache	= Current->mFaceID;						\
		else		*cache	= INVALID_ID;							\
	}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Stabbing query for normal trees.
 *	\param		world_ray		[in] stabbing ray in world space
 *	\param		tree			[in] object's AABB tree
 *	\param		world			[in] object's world matrix, or null
 *	\param		cache			[in] a possibly cached face index, or null
 *	\return		true if success
 *	\warning	SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only.
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool RayCollider::Collide(const Ray& world_ray, const AABBCollisionTree* tree, const Matrix4x4* world, udword* cache)
{
	// Checkings
	if(!tree)					return false;
#ifdef OPC_USE_CALLBACKS
	if(!mObjCallback)			return false;
#else
	if(!mFaces || !mVerts)		return false;
#endif
	// Init collision query
	if(InitQuery(world_ray, world, cache))	return true;

	// Perform stabbing query
	if(IR(mMaxDist)!=IEEE_MAX_FLOAT)	_Stab(tree->GetNodes());
	else								_UnboundedStab(tree->GetNodes());

	// Update cache if needed
	UPDATE_CACHE
	return true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Stabbing query for no-leaf trees.
 *	\param		world_ray		[in] stabbing ray in world space
 *	\param		tree			[in] object's AABB tree
 *	\param		world			[in] object's world matrix, or null
 *	\param		cache			[in] a possibly cached face index, or null
 *	\return		true if success
 *	\warning	SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only.
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool RayCollider::Collide(const Ray& world_ray, const AABBNoLeafTree* tree, const Matrix4x4* world, udword* cache)
{
	// Checkings
	if(!tree)					return false;
#ifdef OPC_USE_CALLBACKS
	if(!mObjCallback)			return false;
#else
	if(!mFaces || !mVerts)		return false;
#endif

	// Init collision query
	if(InitQuery(world_ray, world, cache))	return true;

	// Perform stabbing query
	if(IR(mMaxDist)!=IEEE_MAX_FLOAT)	_Stab(tree->GetNodes());
	else								_UnboundedStab(tree->GetNodes());

	// Update cache if needed
	UPDATE_CACHE
	return true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Stabbing query for quantized trees.
 *	\param		world_ray		[in] stabbing ray in world space
 *	\param		tree			[in] object's AABB tree
 *	\param		world			[in] object's world matrix, or null
 *	\param		cache			[in] a possibly cached face index, or null
 *	\return		true if success
 *	\warning	SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only.
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool RayCollider::Collide(const Ray& world_ray, const AABBQuantizedTree* tree, const Matrix4x4* world, udword* cache)
{
	// Checkings
	if(!tree)					return false;
#ifdef OPC_USE_CALLBACKS
	if(!mObjCallback)			return false;
#else
	if(!mFaces || !mVerts)		return false;
#endif

	// Init collision query
	if(InitQuery(world_ray, world, cache))	return true;

	// Setup dequantization coeffs
	mCenterCoeff	= tree->mCenterCoeff;
	mExtentsCoeff	= tree->mExtentsCoeff;

	// Perform stabbing query
	if(IR(mMaxDist)!=IEEE_MAX_FLOAT)	_Stab(tree->GetNodes());
	else								_UnboundedStab(tree->GetNodes());

	// Update cache if needed
	UPDATE_CACHE
	return true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Stabbing query for quantized no-leaf trees.
 *	\param		world_ray		[in] stabbing ray in world space
 *	\param		tree			[in] object's AABB tree
 *	\param		world			[in] object's world matrix, or null
 *	\param		cache			[in] a possibly cached face index, or null
 *	\return		true if success
 *	\warning	SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only.
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool RayCollider::Collide(const Ray& world_ray, const AABBQuantizedNoLeafTree* tree, const Matrix4x4* world, udword* cache)
{
	// Checkings
	if(!tree)					return false;
#ifdef OPC_USE_CALLBACKS
	if(!mObjCallback)			return false;
#else
	if(!mFaces || !mVerts)		return false;
#endif

	// Init collision query
	if(InitQuery(world_ray, world, cache))	return true;

	// Setup dequantization coeffs
	mCenterCoeff	= tree->mCenterCoeff;
	mExtentsCoeff	= tree->mExtentsCoeff;

	// Perform stabbing query
	if(IR(mMaxDist)!=IEEE_MAX_FLOAT)	_Stab(tree->GetNodes());
	else								_UnboundedStab(tree->GetNodes());

	// Update cache if needed
	UPDATE_CACHE
	return true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Stabbing query for vanilla AABB trees.
 *	\param		world_ray		[in] stabbing ray in world space
 *	\param		tree			[in] AABB tree
 *	\param		box_indices		[out] indices of stabbed boxes
 *	\return		true if success
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool RayCollider::Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices)
{
	// ### bad design here

	// This is typically called for a scene tree, full of -AABBs-, not full of triangles.
	// So we don't really have "primitives" to deal with. Hence it doesn't work with
	// "FirstContact" + "TemporalCoherence".
	ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) );

	// Checkings
	if(!tree)					return false;

	// Init collision query
	// Basically this is only called to initialize precomputed data
	if(InitQuery(world_ray))	return true;

	// Perform stabbing query
	if(IR(mMaxDist)!=IEEE_MAX_FLOAT)	_Stab(tree, box_indices);
	else								_UnboundedStab(tree, box_indices);

	return true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Recursive stabbing query for normal AABB trees.
 *	\param		node	[in] current collision node
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RayCollider::_Stab(const AABBCollisionNode* node)
{
	// Perform Segment-AABB overlap test
	if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;

	if(node->IsLeaf())
	{
		STAB_PRIM(node->GetPrimitive())
	}
	else
	{
		_Stab(node->GetPos());

		if(ContactFound()) return;

		_Stab(node->GetNeg());
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Recursive stabbing query for quantized AABB trees.
 *	\param		node	[in] current collision node
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RayCollider::_Stab(const AABBQuantizedNode* node)
{
	// Dequantize box
	const QuantizedAABB* Box = &node->mAABB;
	const Point Center(float(Box->mCenter[0]) * mCenterCoeff.x, float(Box->mCenter[1]) * mCenterCoeff.y, float(Box->mCenter[2]) * mCenterCoeff.z);
	const Point Extents(float(Box->mExtents[0]) * mExtentsCoeff.x, float(Box->mExtents[1]) * mExtentsCoeff.y, float(Box->mExtents[2]) * mExtentsCoeff.z);

	// Perform Segment-AABB overlap test
	if(!SegmentAABBOverlap(Center, Extents))	return;

	if(node->IsLeaf())
	{
		STAB_PRIM(node->GetPrimitive())
	}
	else
	{
		_Stab(node->GetPos());

		if(ContactFound()) return;

		_Stab(node->GetNeg());
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Recursive stabbing query for no-leaf AABB trees.
 *	\param		node	[in] current collision node
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RayCollider::_Stab(const AABBNoLeafNode* node)
{
	// Perform Segment-AABB overlap test
	if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;

	if(node->HasLeaf())
	{
		STAB_PRIM(node->GetPrimitive())
	}
	else _Stab(node->GetPos());

	if(ContactFound()) return;

	if(node->HasLeaf2())
	{
		STAB_PRIM(node->GetPrimitive2())
	}
	else _Stab(node->GetNeg());
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Recursive stabbing query for quantized no-leaf AABB trees.
 *	\param		node	[in] current collision node
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RayCollider::_Stab(const AABBQuantizedNoLeafNode* node)
{
	// Dequantize box
	const QuantizedAABB* Box = &node->mAABB;
	const Point Center(float(Box->mCenter[0]) * mCenterCoeff.x, float(Box->mCenter[1]) * mCenterCoeff.y, float(Box->mCenter[2]) * mCenterCoeff.z);
	const Point Extents(float(Box->mExtents[0]) * mExtentsCoeff.x, float(Box->mExtents[1]) * mExtentsCoeff.y, float(Box->mExtents[2]) * mExtentsCoeff.z);

	// Perform Segment-AABB overlap test
	if(!SegmentAABBOverlap(Center, Extents))	return;

	if(node->HasLeaf())
	{
		STAB_PRIM(node->GetPrimitive())
	}
	else _Stab(node->GetPos());

	if(ContactFound()) return;

	if(node->HasLeaf2())
	{
		STAB_PRIM(node->GetPrimitive2())
	}
	else _Stab(node->GetNeg());
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Recursive stabbing query for vanilla AABB trees.
 *	\param		node		[in] current collision node
 *	\param		box_indices	[out] indices of stabbed boxes
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RayCollider::_Stab(const AABBTreeNode* node, Container& box_indices)
{
	// Test the box against the segment
	Point Center, Extents;
	node->GetAABB()->GetCenter(Center);
	node->GetAABB()->GetExtents(Extents);
	if(!SegmentAABBOverlap(Center, Extents))	return;

	if(node->IsLeaf())
	{
		box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives());
	}
	else
	{
		_Stab(node->GetPos(), box_indices);
		_Stab(node->GetNeg(), box_indices);
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Recursive stabbing query for normal AABB trees.
 *	\param		node	[in] current collision node
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RayCollider::_UnboundedStab(const AABBCollisionNode* node)
{
	// Perform Ray-AABB overlap test
	if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;

	if(node->IsLeaf())
	{
		UNBOUNDED_STAB_PRIM(node->GetPrimitive())
	}
	else
	{
		_UnboundedStab(node->GetPos());

		if(ContactFound()) return;

		_UnboundedStab(node->GetNeg());
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Recursive stabbing query for quantized AABB trees.
 *	\param		node	[in] current collision node
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RayCollider::_UnboundedStab(const AABBQuantizedNode* node)
{
	// Dequantize box
	const QuantizedAABB* Box = &node->mAABB;
	const Point Center(float(Box->mCenter[0]) * mCenterCoeff.x, float(Box->mCenter[1]) * mCenterCoeff.y, float(Box->mCenter[2]) * mCenterCoeff.z);
	const Point Extents(float(Box->mExtents[0]) * mExtentsCoeff.x, float(Box->mExtents[1]) * mExtentsCoeff.y, float(Box->mExtents[2]) * mExtentsCoeff.z);

	// Perform Ray-AABB overlap test
	if(!RayAABBOverlap(Center, Extents))	return;

	if(node->IsLeaf())
	{
		UNBOUNDED_STAB_PRIM(node->GetPrimitive())
	}
	else
	{
		_UnboundedStab(node->GetPos());

		if(ContactFound()) return;

		_UnboundedStab(node->GetNeg());
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Recursive stabbing query for no-leaf AABB trees.
 *	\param		node	[in] current collision node
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RayCollider::_UnboundedStab(const AABBNoLeafNode* node)
{
	// Perform Ray-AABB overlap test
	if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;

	if(node->HasLeaf())
	{
		UNBOUNDED_STAB_PRIM(node->GetPrimitive())
	}
	else _UnboundedStab(node->GetPos());

	if(ContactFound()) return;

	if(node->HasLeaf2())
	{
		UNBOUNDED_STAB_PRIM(node->GetPrimitive2())
	}
	else _UnboundedStab(node->GetNeg());
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Recursive stabbing query for quantized no-leaf AABB trees.
 *	\param		node	[in] current collision node
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RayCollider::_UnboundedStab(const AABBQuantizedNoLeafNode* node)
{
	// Dequantize box
	const QuantizedAABB* Box = &node->mAABB;
	const Point Center(float(Box->mCenter[0]) * mCenterCoeff.x, float(Box->mCenter[1]) * mCenterCoeff.y, float(Box->mCenter[2]) * mCenterCoeff.z);
	const Point Extents(float(Box->mExtents[0]) * mExtentsCoeff.x, float(Box->mExtents[1]) * mExtentsCoeff.y, float(Box->mExtents[2]) * mExtentsCoeff.z);

	// Perform Ray-AABB overlap test
	if(!RayAABBOverlap(Center, Extents))	return;

	if(node->HasLeaf())
	{
		UNBOUNDED_STAB_PRIM(node->GetPrimitive())
	}
	else _UnboundedStab(node->GetPos());

	if(ContactFound()) return;

	if(node->HasLeaf2())
	{
		UNBOUNDED_STAB_PRIM(node->GetPrimitive2())
	}
	else _UnboundedStab(node->GetNeg());
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Recursive stabbing query for vanilla AABB trees.
 *	\param		node		[in] current collision node
 *	\param		box_indices	[out] indices of stabbed boxes
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RayCollider::_UnboundedStab(const AABBTreeNode* node, Container& box_indices)
{
	// Test the box against the ray
	Point Center, Extents;
	node->GetAABB()->GetCenter(Center);
	node->GetAABB()->GetExtents(Extents);
	if(!RayAABBOverlap(Center, Extents))	return;

	if(node->IsLeaf())
	{
		box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives());
	}
	else
	{
		_UnboundedStab(node->GetPos(), box_indices);
		_UnboundedStab(node->GetNeg(), box_indices);
	}
}


text:
//
//  Copyright (c) 2016 Google Inc.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

#import "FUIAuth.h"

@class FUIAuthBaseViewController;

/** @typedef FUIEmailHintSignInCallback
    @brief The type of block invoked when an emailHint sign-in event completes.

    @param authResult Optionally; Result of sign-in request containing both the user and
       the additional user info associated with the user.
    @param error Optionally; the error which occurred - or nil if the request was successful.
    @param credential Optionally; The credential used to sign-in.
 */
typedef void (^FUIEmailHintSignInCallback)(FIRAuthDataResult *_Nullable authResult,
                                           NSError *_Nullable error,
                                           FIRAuthCredential *_Nullable credential);

NS_ASSUME_NONNULL_BEGIN

/**
 * The methods defined in this file are for use in the FirebaseUI provider libraries.
 * They may break in non-major releases and are not for public use.
 */
@protocol FUIEmailAuthProvider <NSObject>

- (void)handleAccountLinkingForEmail:(NSString *)email
                       newCredential:(FIRAuthCredential *)newCredential
            presentingViewController:(UIViewController *)presentingViewController
                        signInResult:(_Nullable FIRAuthResultCallback)result;

- (void)signInWithEmailHint:(NSString *)emailHint
   presentingViewController:(FUIAuthBaseViewController *)presentingViewController
              originalError:(NSError *)originalError
                 completion:(FUIEmailHintSignInCallback)completion;

@end

@interface FUIAuth ()

/** @fn invokeResultCallbackWithAuthDataResult:error:
    @brief Invokes the auth UI result callback.
    @param authDataResult The sign in data result, if any.
    @param url The url, if any.
    @param error The error which occurred, if any.
 */
- (void)invokeResultCallbackWithAuthDataResult:(nullable FIRAuthDataResult *)authDataResult
                                           URL:(nullable NSURL *)url
                                         error:(nullable NSError *)error;

/** @fn invokeOperationCallback:error:
    @brief Invokes the auth UI operation callback.
    @param operation The executed operation.
    @param error The error which occurred, if any.
 */
- (void)invokeOperationCallback:(FUIAccountSettingsOperationType)operation
                          error:(NSError *_Nullable)error;

/** @fn providerWithID:
    @brief Returns first provider (if it exists) with specified provider ID.
    @param providerID The ID of the provider.
 */
- (nullable id<FUIAuthProvider>)providerWithID:(NSString *)providerID;

/** @fn signInWithProviderUI:presentingViewController:defaultValue:
    @brief Signs in with specified provider.
        @see FUIAuthDelegate.authUI:didSignInWithAuthDataResult:URL:error: for method callback.
    @param providerUI The authentication provider used for signing in.
    @param presentingViewController The view controller used to present the UI.
    @param defaultValue The provider default initialization value (e.g. email or phone number)
        used for signing in.
 */
- (void)signInWithProviderUI:(id<FUIAuthProvider>)providerUI
    presentingViewController:(UIViewController *)presentingViewController
                defaultValue:(nullable NSString *)defaultValue;

/** @property emailAuthProvider
    @brief The email auth provider, if any, that will be displayed in the default sign-in UI.
 */
@property(nonatomic, weak, nullable) id<FUIEmailAuthProvider> emailAuthProvider;

/** @property emulatorEnabled
    @brief Whether or not the auth emulator is being used.
 */
@property(nonatomic, assign, getter=isEmulatorEnabled) BOOL emulatorEnabled;

@end

NS_ASSUME_NONNULL_END

redpajama_set_name: RedPajamaGithub


text:
import React, { Component } from 'react';
import { provideHooks } from 'redial';

@provideHooks({
  defer: ({ setProps, getProps }) => new Promise((resolve) => {
    const { color } = getProps();
    if(!color) {
      if (typeof window === 'object') {
        throw new Error('Defer: Demo error on client side only');
      }
      setTimeout(() => {
        const getValue = () => Math.round(Math.random() * 255);
        setProps({color: `rgb(${getValue()}, ${getValue()}, ${getValue()})`});
        resolve();
      }, 1000);
    } else {
      resolve();
    }
  })
})
export default class Fetch extends Component {
  render() {
    return (

Client will get error on blocking

    );
  }
}


text:
/*
 * Do not modify this file. This file is generated from the sts-2011-06-15.normal.json service model.
 */
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.Text;
using System.IO;

using Amazon.Runtime;
using Amazon.Runtime.Internal;

namespace Amazon.SecurityToken.Model
{
    ///
    /// Contains the response to a successful GetSessionToken request, including temporary
    /// AWS credentials that can be used to make AWS requests.
    ///
    public partial class GetSessionTokenResponse : AmazonWebServiceResponse
    {
        private Credentials _credentials;

        ///
        /// Gets and sets the property Credentials.
        /// <para>
        /// The session credentials for API authentication.
        /// </para>
        ///
        public Credentials Credentials
        {
            get { return this._credentials; }
            set { this._credentials = value; }
        }

        // Check to see if Credentials property is set
        internal bool IsSetCredentials()
        {
            return this._credentials != null;
        }

    }
}


text:
import {Post} from './post'

export {
    Post
}


text:
<!DOCTYPE html>

    <title>%(DocumentTitle)</title>

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">

    %(HeadContent)


text:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- From: file:/C:/android/myDev/facebook-android-sdk-3.22.0/facebook/res/values-xhdpi/dimens.xml -->
    <eat-comment/>
    <dimen name="com_facebook_picker_divider_width">2px</dimen>
</resources>


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ZocMonLib.Web.AspNet.Test.Site
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }
    }
}


text:
import Sequelize from 'sequelize'
import {buildAndAddGetModelConnectorsServices} from "../connector";
import {createCore} from 'injectable-core'
import {createSequelize} from './shared'

const sequelize = createSequelize()
const PostModel = sequelize.define('Post', {
	title: Sequelize.STRING,
	comment: Sequelize.STRING
})

const createNewCore = () => {
	const core = createCore()
	core.buildAndAddService({
		name: '$getDb',
		func: ({}, _) => sequelize
	})

	return core
}

describe('connector service', () => {
	const core = createNewCore()
	beforeAll(async(done) => {
		await sequelize.sync({force: true})
		done()
	})
	test('should be added', async () => {
		await buildAndAddGetModelConnectorsServices({
			option: {
				connectorMiddlewares: [],
				core
			},
			db: sequelize,
			models: [{name: 'Post'}]
		}).run().promise()

		const getPostConnector = core.getService('getPostConnector')
		const Post = await getPostConnector()
		await Post.create({title: '#1'})
		const post = await Post.findOne()

		expect(post).toEqual(expect.objectContaining({title: '#1'}))
	})
})

describe('connector service with middlewares', () => {
	const core = createNewCore()
	core.buildAndAddService({
		name: 'autoAddComment',
		func: (({}, {model, connector}) => ({
			...connector,
			create: (values, options) => connector.create({...values, comment: 'auto added'}, {...options})
		}))
	})
	beforeAll(async(done) => {
		await sequelize.sync({force: true})
		done()
	})
	test('should be added', async () => {
		await buildAndAddGetModelConnectorsServices({
			option: {
				connectorMiddlewares: ['autoAddComment'],
				core,
			},
			db: sequelize,
			models: [{name: 'Post'}, {name: 'Comment'}]
		}).run().promise()

		const getPostConnector = core.getService('getPostConnector')
		const Post = await getPostConnector()
		await Post.create({title: '#1'})
		const post = await Post.findOne()

		expect(post).toEqual(expect.objectContaining({title: '#1', comment: 'auto added'}))
	})
})


text:
package net.violet.db.cache;

/**
 * Classe de base pour un noeud dans le cache distribué.
 */
abstract class AbstractCacheNode implements CacheNode {

	private CacheNodeListener mListener;

	public void setListener(CacheNodeListener inListener) {
		this.mListener = inListener;
	}

	protected void receiveMessage(CacheMessage inMessage) {
		if (this.mListener != null) {
			this.mListener.receiveMessage(inMessage);
		}
	}

	protected void addedMember(String inName) {
		if (this.mListener != null) {
			this.mListener.addedMember(inName);
		}
	}

	protected void disappearedMember(String inName) {
		if (this.mListener != null) {
			this.mListener.disappearedMember(inName);
		}
	}
}


text:
using System;
using System.Collections.Generic;

using Xamarin.Forms;
using Conference.Clients.Portable;
using System.Text.RegularExpressions;

namespace Conference.Clients.UI
{
    public partial class LoginPage : ContentPage
    {
        const string emailRegex = @"^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
            @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$";
        ImageSource placeholder;
        LoginViewModel vm;
        public LoginPage()
        {
            InitializeComponent();
            BindingContext = vm = new LoginViewModel(Navigation);

            if (!Settings.Current.FirstRun)
            {
                Title = "My Account";
                var cancel = new ToolbarItem
                {
                    Text = "Cancel",
                    Command = new Command(async() =>
                            {
                                if(vm.IsBusy)
                                    return;
                                await Navigation.PopModalAsync();
                            })
                };
                ToolbarItems.Add(cancel);

                if (Device.RuntimePlatform != Device.iOS)
                    cancel.Icon = "toolbar_close.png";
            }

            CircleImageAvatar.Source = placeholder = ImageSource.FromFile("profile_generic_big.png");
            EntryEmail.TextChanged += (sender, e) =>
                {
                    var isValid = (Regex.IsMatch(e.NewTextValue, emailRegex, RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250)));
                    if(isValid)
                    {
                        Device.BeginInvokeOnMainThread(()=>
                            {
                                CircleImageAvatar.BorderThickness = 3;
                                CircleImageAvatar.Source = ImageSource.FromUri(new Uri(Gravatar.GetURL(EntryEmail.Text)));
                            });

                    }
                    else if(CircleImageAvatar.Source != placeholder)
                    {
                        Device.BeginInvokeOnMainThread(()=>
                            {
                                CircleImageAvatar.BorderThickness = 0;
                                CircleImageAvatar.Source = placeholder;
                            });
                    }
                };
        }

        protected override bool OnBackButtonPressed()
        {
            if(Settings.Current.FirstRun)
                return true;

            return base.OnBackButtonPressed();
        }
    }
}


text:
@interface JJBaseTabBarController : UITabBarController

@end


text:
from .services.private_catalog import PrivateCatalogAsyncClient, PrivateCatalogClient
from .types.private_catalog import (
    AssetReference,
    Catalog,
    GcsSource,
    GitSource,
    Inputs,
    Product,
    SearchCatalogsRequest,
    SearchCatalogsResponse,
    SearchProductsRequest,
    SearchProductsResponse,
    SearchVersionsRequest,
    SearchVersionsResponse,
    Version,
)

__all__ = (
    "PrivateCatalogAsyncClient",
    "AssetReference",
    "Catalog",
    "GcsSource",
    "GitSource",
    "Inputs",
    "PrivateCatalogClient",
    "Product",
    "SearchCatalogsRequest",
    "SearchCatalogsResponse",
    "SearchProductsRequest",
    "SearchProductsResponse",
    "SearchVersionsRequest",
    "SearchVersionsResponse",
    "Version",
)


text:
<?php

use yii\helpers\Html;
use yii\widgets\ActiveForm;

/* @var $this yii\web\View */
/* @var $model frontend\models\PenganjuranKursusPesertaSukanSearch */
/* @var $form yii\widgets\ActiveForm */
?>

    <?php $form = ActiveForm::begin([
        'action' => ['index'],
        'method' => 'get',
    ]); ?>

    <?= $form->field($model, 'penganjuran_kursus_peserta_sukan_id') ?>

    <?= $form->field($model, 'penganjuran_kursus_peserta_id') ?>

    <?= $form->field($model, 'jenis_sukan') ?>

    <?= $form->field($model, 'tahap') ?>

    <?= $form->field($model, 'tahun') ?>

    <?php // echo $form->field($model, 'created_by') ?>

    <?php // echo $form->field($model, 'updated_by') ?>

    <?php // echo $form->field($model, 'created') ?>

    <?php // echo $form->field($model, 'updated') ?>

        <?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?>
        <?= Html::resetButton('Reset', ['class' => 'btn btn-default']) ?>

    <?php ActiveForm::end(); ?>


text:
#include "gazebo/common/Exception.hh"
#include "gazebo/common/Image.hh"

#include "gazebo/physics/World.hh"

#include "gazebo/transport/transport.hh"
#include "gazebo/msgs/msgs.hh"

#include "gazebo/rendering/RenderEngine.hh"
#include "gazebo/rendering/Camera.hh"
#include "gazebo/rendering/Scene.hh"
#include "gazebo/rendering/RenderingIface.hh"

#include "gazebo/sensors/SensorFactory.hh"
#include "gazebo/sensors/MultiCameraSensor.hh"

using namespace gazebo;
using namespace sensors;

GZ_REGISTER_STATIC_SENSOR("multicamera", MultiCameraSensor)

//////////////////////////////////////////////////
MultiCameraSensor::MultiCameraSensor()
    : Sensor(sensors::IMAGE)
{
}

//////////////////////////////////////////////////
MultiCameraSensor::~MultiCameraSensor()
{
}

//////////////////////////////////////////////////
std::string MultiCameraSensor::GetTopic() const
{
  std::string topic = Sensor::GetTopic();

  // Create a topic name if one has not been specified.
  if (topic.empty())
  {
    topic = "~/";
    topic += this->parentName + "/" + this->GetName() + "/images";
    boost::replace_all(topic, "::", "/");
  }

  return topic;
}

//////////////////////////////////////////////////
void MultiCameraSensor::Load(const std::string &_worldName)
{
  Sensor::Load(_worldName);

  // Create the publisher of image data.
  this->imagePub = this->node->Advertise<msgs::ImagesStamped>(
      this->GetTopic(), 50);
}

//////////////////////////////////////////////////
void MultiCameraSensor::Init()
{
  if (rendering::RenderEngine::Instance()->GetRenderPathType() ==
      rendering::RenderEngine::NONE)
  {
    gzerr << "Unable to create MultiCameraSensor. Rendering is disabled.\n";
    return;
  }

  std::string worldName = this->world->GetName();

  if (worldName.empty())
  {
    gzerr << "No world name\n";
    return;
  }

  this->scene = rendering::get_scene(worldName);

  if (!this->scene)
  {
    this->scene = rendering::create_scene(worldName, false);

    // This usually means rendering is not available
    if (!this->scene)
    {
      gzerr << "Unable to create MultiCameraSensor.\n";
      return;
    }
  }

  // Create and initialize all the cameras
  sdf::ElementPtr cameraSdf = this->sdf->GetElement("camera");
  while (cameraSdf)
  {
    rendering::CameraPtr camera = this->scene->CreateCamera(
          cameraSdf->GetValueString("name"), false);

    if (!camera)
    {
      gzthrow("Unable to create multicamera sensor[" +
              cameraSdf->GetValueString("name"));
      return;
    }

    camera->SetCaptureData(true);
    camera->Load(cameraSdf);

    // Do some sanity checks
    if (camera->GetImageWidth() == 0 || camera->GetImageHeight() == 0)
      gzthrow("Image has zero size");

    camera->Init();
    camera->CreateRenderTexture(camera->GetName() + "_RttTex");

    math::Pose cameraPose = this->pose;
    if (cameraSdf->HasElement("pose"))
      cameraPose = cameraSdf->GetValuePose("pose") + cameraPose;
    camera->SetWorldPose(cameraPose);
    camera->AttachToVisual(this->parentName, true);

    {
      boost::mutex::scoped_lock lock(this->cameraMutex);
      this->cameras.push_back(camera);
    }

    cameraSdf = cameraSdf->GetNextElement("camera");
  }

  // Disable clouds and moon on server side until fixed and also to improve
  // performance
  this->scene->SetSkyXMode(rendering::Scene::GZ_SKYX_ALL &
      ~rendering::Scene::GZ_SKYX_CLOUDS &
      ~rendering::Scene::GZ_SKYX_MOON);

  Sensor::Init();
}

//////////////////////////////////////////////////
void MultiCameraSensor::Fini()
{
  this->imagePub.reset();
  Sensor::Fini();

  boost::mutex::scoped_lock lock(this->cameraMutex);

  for (std::vector<rendering::CameraPtr>::iterator iter =
      this->cameras.begin(); iter != this->cameras.end(); ++iter)
  {
    (*iter)->GetScene()->RemoveCamera((*iter)->GetName());
  }
  this->cameras.clear();
  this->scene.reset();
}

//////////////////////////////////////////////////
rendering::CameraPtr MultiCameraSensor::GetCamera(unsigned int _index) const
{
  boost::mutex::scoped_lock lock(this->cameraMutex);

  if (_index < this->cameras.size())
    return this->cameras[_index];
  else
    gzthrow("camera index out of range. Valid range[0.." +
        boost::lexical_cast<std::string>(this->cameras.size()-1));
}

//////////////////////////////////////////////////
void MultiCameraSensor::UpdateImpl(bool /*_force*/)
{
  boost::mutex::scoped_lock lock(this->cameraMutex);

  if (this->cameras.size() == 0)
    return;

  bool publish = this->imagePub->HasConnections();

  this->lastMeasurementTime = this->scene->GetSimTime();

  msgs::ImagesStamped msg;
  msgs::Set(msg.mutable_time(), this->lastMeasurementTime);

  // Update all the cameras
  for (std::vector<rendering::CameraPtr>::iterator iter = this->cameras.begin();
       iter != this->cameras.end(); ++iter)
  {
    (*iter)->Render();
    (*iter)->PostRender();

    if (publish)
    {
      msgs::Image *image = msg.add_image();
      image->set_width((*iter)->GetImageWidth());
      image->set_height((*iter)->GetImageHeight());
      image->set_pixel_format(common::Image::ConvertPixelFormat(
            (*iter)->GetImageFormat()));
      image->set_step((*iter)->GetImageWidth() * (*iter)->GetImageDepth());
      image->set_data((*iter)->GetImageData(0),
          image->width() * (*iter)->GetImageDepth() * image->height());
    }
  }

  if (publish)
    this->imagePub->Publish(msg);
}

//////////////////////////////////////////////////
unsigned int MultiCameraSensor::GetCameraCount() const
{
  boost::mutex::scoped_lock lock(this->cameraMutex);
  return this->cameras.size();
}

//////////////////////////////////////////////////
unsigned int MultiCameraSensor::GetImageWidth(unsigned int _index) const
{
  return this->GetCamera(_index)->GetImageWidth();
}

//////////////////////////////////////////////////
unsigned int MultiCameraSensor::GetImageHeight(unsigned int _index) const
{
  return this->GetCamera(_index)->GetImageHeight();
}

//////////////////////////////////////////////////
const unsigned char *MultiCameraSensor::GetImageData(unsigned int _index)
{
  return this->GetCamera(_index)->GetImageData(0);
}

//////////////////////////////////////////////////
bool MultiCameraSensor::SaveFrame(const std::vector<std::string> &_filenames)
{
  this->SetActive(true);

  boost::mutex::scoped_lock lock(this->cameraMutex);
  if (_filenames.size() != this->cameras.size())
  {
    gzerr << "Filename count[" << _filenames.size() << "] does not match "
          << "camera count[" << this->cameras.size() << "]\n";
    return false;
  }

  bool result = true;

  std::vector<rendering::CameraPtr>::iterator citer = this->cameras.begin();
  for (std::vector<std::string>::const_iterator fiter = _filenames.begin();
       fiter != _filenames.end(); ++fiter, ++citer)
  {
    result &= (*citer)->SaveFrame(*fiter);
  }

  return result;
}

//////////////////////////////////////////////////
bool MultiCameraSensor::IsActive()
{
  return Sensor::IsActive() ||
    (this->imagePub && this->imagePub->HasConnections());
}


text:
namespace embedder_support {

content::AllowServiceWorkerResult AllowServiceWorker(
    const GURL& scope,
    const net::SiteForCookies& site_for_cookies,
    const absl::optional<url::Origin>& top_frame_origin,
    const content_settings::CookieSettings* cookie_settings,
    const HostContentSettingsMap* settings_map) {
  GURL first_party_url = top_frame_origin ? top_frame_origin->GetURL() : GURL();
  // Check if JavaScript is allowed.
  content_settings::SettingInfo info;
  std::unique_ptr<base::Value> value = settings_map->GetWebsiteSetting(
      first_party_url, first_party_url, ContentSettingsType::JAVASCRIPT, &info);
  ContentSetting setting = content_settings::ValueToContentSetting(value.get());
  bool allow_javascript = setting == CONTENT_SETTING_ALLOW;

  // Check if cookies are allowed.
  bool allow_cookies = cookie_settings->IsFullCookieAccessAllowed(
      scope, site_for_cookies, top_frame_origin);

  return content::AllowServiceWorkerResult::FromPolicy(!allow_javascript,
                                                       !allow_cookies);
}

bool AllowSharedWorker(
    const GURL& worker_url,
    const net::SiteForCookies& site_for_cookies,
    const absl::optional<url::Origin>& top_frame_origin,
    const std::string& name,
    const blink::StorageKey& storage_key,
    int render_process_id,
    int render_frame_id,
    const content_settings::CookieSettings* cookie_settings) {
  bool allow = cookie_settings->IsFullCookieAccessAllowed(
      worker_url, site_for_cookies, top_frame_origin);

  content_settings::PageSpecificContentSettings::SharedWorkerAccessed(
      render_process_id, render_frame_id, worker_url, name, storage_key,
      !allow);
  return allow;
}

bool AllowWorkerFileSystem(
    const GURL& url,
    const std::vector<content::GlobalRenderFrameHostId>& render_frames,
    const content_settings::CookieSettings* cookie_settings) {
  bool allow = cookie_settings->IsFullCookieAccessAllowed(
      url, net::SiteForCookies::FromUrl(url), url::Origin::Create(url));
  for (const auto& it : render_frames) {
    content_settings::PageSpecificContentSettings::FileSystemAccessed(
        it.child_id, it.frame_routing_id, url, !allow);
  }
  return allow;
}

bool AllowWorkerIndexedDB(
    const GURL& url,
    const std::vector<content::GlobalRenderFrameHostId>& render_frames,
    const content_settings::CookieSettings* cookie_settings) {
  bool allow = cookie_settings->IsFullCookieAccessAllowed(
      url, net::SiteForCookies::FromUrl(url), url::Origin::Create(url));

  for (const auto& it : render_frames) {
    content_settings::PageSpecificContentSettings::IndexedDBAccessed(
        it.child_id, it.frame_routing_id, url, !allow);
  }
  return allow;
}

bool AllowWorkerCacheStorage(
    const GURL& url,
    const std::vector<content::GlobalRenderFrameHostId>& render_frames,
    const content_settings::CookieSettings* cookie_settings) {
  bool allow = cookie_settings->IsFullCookieAccessAllowed(
      url, net::SiteForCookies::FromUrl(url), url::Origin::Create(url));

  for (const auto& it : render_frames) {
    content_settings::PageSpecificContentSettings::CacheStorageAccessed(
        it.child_id, it.frame_routing_id, url, !allow);
  }
  return allow;
}

bool AllowWorkerWebLocks(
    const GURL& url,
    const content_settings::CookieSettings* cookie_settings) {
  return cookie_settings->IsFullCookieAccessAllowed(
      url, net::SiteForCookies::FromUrl(url), url::Origin::Create(url));
}

}  // namespace embedder_support


text:
<!--- Copyright (C) 2009-2017 Lightbend Inc. <https://www.lightbend.com> -->
# The Play cache API

Caching data is a typical optimization in modern applications, and so Play provides a global cache.

> An important point about the cache is that it behaves just like a cache should: the data you just stored may just go missing.

For any data stored in the cache, a regeneration strategy needs to be put in place in case the data goes missing. This philosophy is one of the fundamentals behind Play, and is different from Java EE, where the session is expected to retain values throughout its lifetime.

The default implementation of the Cache API uses [EHCache](http://ehcache.org/).

## Importing the Cache API

Add `cache` into your dependencies list. For example, in `build.sbt`:

```scala
libraryDependencies ++= Seq(
  cache,
  ...
)
```

## Accessing the Cache API

The cache API is defined by the [AsyncCacheApi](api/scala/play/api/cache/AsyncCacheApi.html) and [SyncCacheApi](api/scala/play/api/cache/SyncCacheApi.html) traits, depending on whether you want an asynchronous or synchronous implementation, and can be injected into your component like any other dependency.  For example:

@[inject](code/ScalaCache.scala)

> **Note:** The API is intentionally minimal to allow several implementation to be plugged in. If you need a more specific API, use the one provided by your Cache plugin.

Using this simple API you can store data in cache:

@[set-value](code/ScalaCache.scala)

And then retrieve it later:

@[get-value](code/ScalaCache.scala)

There is also a convenient helper to retrieve from cache or set the value in cache if it was missing:

@[retrieve-missing](code/ScalaCache.scala)

You can specify an expiry duration by passing a duration, by default the duration is infinite:

@[set-value-expiration](code/ScalaCache.scala)

To remove an item from the cache use the `remove` method:

@[remove-value](code/ScalaCache.scala)

Note that the [SyncCacheApi](api/scala/play/api/cache/SyncCacheApi.html) has the same API, except it returns the values directly instead of using futures.

## Accessing different caches

It is possible to access different caches.  The default cache is called `play`, and can be configured by creating a file called `ehcache.xml`.  Additional caches may be configured with different configurations, or even implementations.

If you want to access multiple different ehcache caches, then you'll need to tell Play to bind them in `application.conf`, like so:

    play.cache.bindCaches = ["db-cache", "user-cache", "session-cache"]

By default, Play will try to create these caches for you. If you would like to define them yourself in `ehcache.xml`, you can set:

    play.cache.createBoundCaches = false

Now to access these different caches, when you inject them, use the [NamedCache](api/java/play/cache/NamedCache.html) qualifier on your dependency, for example:

@[qualified](code/ScalaCache.scala)

## Caching HTTP responses

You can easily create smart cached actions using standard Action composition.

> **Note:** Play HTTP `Result` instances are safe to cache and reuse later.

The [Cached](api/scala/play/api/cache/Cached.html) class helps you build cached actions.

@[cached-action-app](code/ScalaCache.scala)

You can cache the result of an action using a fixed key like `"homePage"`.

@[cached-action](code/ScalaCache.scala)

If results vary, you can cache each result using a different key. In this example, each user has a different cached result.

@[composition-cached-action](code/ScalaCache.scala)

### Control caching

You can easily control what you want to cache or what you want to exclude from the cache.

You may want to only cache 200 Ok results.

@[cached-action-control](code/ScalaCache.scala)

Or cache 404 Not Found only for a couple of minutes

@[cached-action-control-404](code/ScalaCache.scala)

## Custom implementations

It is possible to provide a custom implementation of the cache API that either replaces, or sits along side the default implementation.

To replace the default implementation, you'll need to disable the default implementation by setting the following in `application.conf`:

```
play.modules.disabled += "play.api.cache.EhCacheModule"
```

You can then implement [AsyncCacheApi](api/java/play/cache/AsyncCacheApi.html) and bind it in the DI container. You can also bind [SyncCacheApi](api/java/play/cache/SyncCacheApi.html) to [DefaultSyncCacheApi](api/java/play/cache/DefaultSyncCacheApi.html), which simply wraps the async implementation.

To provide an implementation of the cache API in addition to the default implementation, you can either create a custom qualifier, or reuse the `NamedCache` qualifier to bind the implementation.


text:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ixq.Core.Entity;
using Ixq.Data.DataAnnotations;

namespace Ixq.Demo.Domain.Dtos
{
    public abstract class DtoBase<TEntity> : Core.Dto.DtoBase<TEntity>
        where TEntity : class, IEntity<Guid>, new()
    {
        [Key]
        [Required]
        [Hide(IsHiddenOnCreate = true, IsHiddenOnDetail = true, IsHiddenOnEdit = true, IsHiddenOnView = false)]
        [Display(Name = "唯一标识", Order = 0)]
        public override Guid Id { get; set; }
    }
}


text:
package org.hisp.dhis.dashboard.impl;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import lombok.RequiredArgsConstructor;

import org.apache.commons.collections4.MapUtils;
import org.hisp.dhis.category.Category;
import org.hisp.dhis.category.CategoryDimension;
import org.hisp.dhis.category.CategoryOption;
import org.hisp.dhis.category.CategoryOptionGroup;
import org.hisp.dhis.category.CategoryOptionGroupSet;
import org.hisp.dhis.category.CategoryOptionGroupSetDimension;
import org.hisp.dhis.common.BaseAnalyticalObject;
import org.hisp.dhis.common.IdentifiableObject;
import org.hisp.dhis.common.IdentifiableObjectManager;
import org.hisp.dhis.commons.collection.CollectionUtils;
import org.hisp.dhis.dashboard.Dashboard;
import org.hisp.dhis.dataelement.DataElement;
import org.hisp.dhis.dataelement.DataElementGroup;
import org.hisp.dhis.dataelement.DataElementGroupSet;
import org.hisp.dhis.dataelement.DataElementGroupSetDimension;
import org.hisp.dhis.eventchart.EventChart;
import org.hisp.dhis.eventreport.EventReport;
import org.hisp.dhis.eventvisualization.EventVisualization;
import org.hisp.dhis.feedback.ErrorCode;
import org.hisp.dhis.feedback.ErrorReport;
import org.hisp.dhis.hibernate.HibernateProxyUtils;
import org.hisp.dhis.indicator.Indicator;
import org.hisp.dhis.legend.LegendSet;
import org.hisp.dhis.program.ProgramStage;
import org.hisp.dhis.schema.SchemaService;
import org.hisp.dhis.security.acl.AccessStringHelper;
import org.hisp.dhis.security.acl.AclService;
import org.hisp.dhis.sharing.AccessObject;
import org.hisp.dhis.sharing.CascadeSharingParameters;
import org.hisp.dhis.sharing.CascadeSharingReport;
import org.hisp.dhis.sharing.CascadeSharingService;
import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
import org.hisp.dhis.trackedentity.TrackedEntityAttributeDimension;
import org.hisp.dhis.trackedentity.TrackedEntityDataElementDimension;
import org.hisp.dhis.user.sharing.Sharing;
import org.hisp.dhis.user.sharing.UserAccess;
import org.hisp.dhis.user.sharing.UserGroupAccess;
import org.hisp.dhis.visualization.Visualization;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class DefaultCascadeSharingService
    implements CascadeSharingService
{
    private final IdentifiableObjectManager manager;

    private final SchemaService schemaService;

    private final AclService aclService;

    @Override
    @Transactional
    public CascadeSharingReport cascadeSharing( Dashboard dashboard, CascadeSharingParameters parameters )
    {
        if ( CollectionUtils.isEmpty( dashboard.getItems() ) )
        {
            return parameters.getReport();
        }

        Set<IdentifiableObject> canMergeObjects = new HashSet<>();

        dashboard.getItems().forEach( dashboardItem -> {

            Set<IdentifiableObject> itemCanMergeObjects = new HashSet<>();

            switch ( dashboardItem.getType() )
            {
            case MAP:
                handleMapObject( dashboard.getSharing(), dashboardItem.getMap(), itemCanMergeObjects, parameters );
                break;
            case VISUALIZATION:
                handleVisualization( dashboard.getSharing(), dashboardItem.getVisualization(), itemCanMergeObjects,
                    parameters );
                break;
            case EVENT_REPORT:
                handleEventReport( dashboard.getSharing(), dashboardItem.getEventReport(), itemCanMergeObjects,
                    parameters );
                break;
            case EVENT_CHART:
                handleEventChart( dashboard.getSharing(), dashboardItem.getEventChart(), itemCanMergeObjects,
                    parameters );
                break;
            case EVENT_VISUALIZATION:
                handleEventVisualization( dashboard.getSharing(), dashboardItem.getEventVisualization(),
                    itemCanMergeObjects,
                    parameters );
                break;
            default:
                break;
            }

            if ( !CollectionUtils.isEmpty( itemCanMergeObjects ) )
            {
                canMergeObjects.addAll( itemCanMergeObjects );

                if ( !parameters.isAtomic() || !parameters.getReport().hasErrors() )
                {
                    parameters.getReport().incUpdatedDashboardItem();
                }
            }
        } );

        if ( parameters.isAtomic() && parameters.getReport().hasErrors() )
        {
            return parameters.getReport();
        }

        if ( parameters.isDryRun() )
        {
            canMergeObjects
                .forEach( object -> parameters.getReport().addUpdatedObject( getTypeReportKey( object ), object ) );
            return parameters.getReport();
        }

        // All checks done, proceed to update sharing for all objects.
        canMergeObjects.forEach( object -> mergeSharing( dashboard.getSharing(), object, parameters ) );

        return parameters.getReport();
    }

    /**
     * Check if can merge sharing from given dashboard to given Map
     *
     * @param map {@link org.hisp.dhis.mapping.Map}
     * @param canMergeObjects Set of objects need to be updated
     * @param parameters {@link CascadeSharingParameters}
     */
    private void handleMapObject( final Sharing sourceSharing, org.hisp.dhis.mapping.Map map,
        Set<IdentifiableObject> canMergeObjects, CascadeSharingParameters parameters )
    {
        if ( canUserUpdate( map, parameters ) && shouldUpdateSharing( sourceSharing, map ) )
        {
            canMergeObjects.add( map );
        }
    }

    /**
     * Check if can merge sharing from given dashboard to given visualization
     *
     * @param sourceSharing {@link Sharing}
     * @param visualization {@link Visualization}
     * @param parameters {@link CascadeSharingParameters}
     */
    private void handleVisualization( final Sharing sourceSharing, Visualization visualization,
        Set<IdentifiableObject> canMergeObjects, CascadeSharingParameters parameters )
    {
        if ( visualization == null )
        {
            return;
        }

        if ( canUserUpdate( visualization, parameters ) && shouldUpdateSharing( sourceSharing, visualization ) )
        {
            canMergeObjects.add( visualization );
        }

        handleBaseAnalyticObject( sourceSharing, visualization, canMergeObjects, parameters );
    }

    /**
     * Check if can merge sharing from given dashboard to given eventReport
     *
     * @param sourceSharing {@link Sharing}
     * @param eventReport {@link EventReport}
     * @param updateObjects Set of objects need to be updated
     * @param parameters {@link CascadeSharingParameters}
     */
    private void handleEventReport( final Sharing sourceSharing, EventReport eventReport,
        Set<IdentifiableObject> updateObjects,
        CascadeSharingParameters parameters )
    {
        if ( eventReport == null )
        {
            return;
        }

        if ( handleIdentifiableObject( sourceSharing, EventReport.class, eventReport, updateObjects, parameters ) )
        {
            updateObjects.add( eventReport );
        }

        handleIdentifiableObject( sourceSharing, TrackedEntityAttribute.class, eventReport.getAttributeValueDimension(),
            updateObjects,
            parameters );

        handleIdentifiableObject( sourceSharing, DataElement.class, eventReport.getDataElementValueDimension(),
            updateObjects,
            parameters );

        handleBaseAnalyticObject( sourceSharing, eventReport, updateObjects, parameters );
    }

    /**
     * Check if can merge sharing from given dashboard to given eventChart
     *
     * @param sourceSharing {@link Sharing}
     * @param eventChart {@link EventChart}
     * @param updateObjects Set of objects need to be updated
     * @param parameters {@link CascadeSharingParameters}
     */
    private void handleEventChart( final Sharing sourceSharing, EventChart eventChart,
        Set<IdentifiableObject> updateObjects,
        CascadeSharingParameters parameters )
    {
        if ( eventChart == null )
        {
            return;
        }

        if ( handleIdentifiableObject( sourceSharing, EventChart.class, eventChart, updateObjects, parameters ) )
        {
            updateObjects.add( eventChart );
        }

        handleIdentifiableObject( sourceSharing, TrackedEntityAttribute.class, eventChart.getAttributeValueDimension(),
            updateObjects,
            parameters );

        handleIdentifiableObject( sourceSharing, DataElement.class, eventChart.getDataElementValueDimension(),
            updateObjects,
            parameters );

        handleBaseAnalyticObject( sourceSharing, eventChart, updateObjects, parameters );
    }

    /**
     * Handles the sharing cascade for the given Dashboard and
     * EventVisualization
     *
     * @param sourceSharing {@link Sharing}
     * @param eventVisualization {@link EventVisualization}
     * @param updateObjects Set of objects need to be updated
     * @param parameters {@link CascadeSharingParameters}
     */
    private void handleEventVisualization( final Sharing sourceSharing, EventVisualization eventVisualization,
        Set<IdentifiableObject> updateObjects, CascadeSharingParameters parameters )
    {
        if ( eventVisualization == null )
        {
            return;
        }

        if ( handleIdentifiableObject( sourceSharing, EventVisualization.class, eventVisualization, updateObjects,
            parameters ) )
        {
            updateObjects.add( eventVisualization );
        }

        handleIdentifiableObject( sourceSharing, TrackedEntityAttribute.class,
            eventVisualization.getAttributeValueDimension(), updateObjects, parameters );

        handleIdentifiableObject( sourceSharing, DataElement.class, eventVisualization.getDataElementValueDimension(),
            updateObjects, parameters );

        handleBaseAnalyticObject( sourceSharing, eventVisualization, updateObjects, parameters );
    }

    /**
     * Check if can merge sharing from given source to all given
     * analyticalObject's dimensional objects
     *
     * @param sourceSharing {@link Sharing}
     * @param analyticalObject any object extends {@link BaseAnalyticalObject}
     * @param listUpdateObjects Set of objects need to be updated
     * @param parameters {@link CascadeSharingParameters}
     */
    private void handleBaseAnalyticObject( final Sharing sourceSharing, BaseAnalyticalObject analyticalObject,
        Set<IdentifiableObject> listUpdateObjects, CascadeSharingParameters parameters )
    {
        handleIdentifiableObjects( sourceSharing, DataElement.class, analyticalObject.getDataElements(),
            listUpdateObjects,
            parameters );

        handleIdentifiableObjects( sourceSharing, Indicator.class, analyticalObject.getIndicators(), listUpdateObjects,
            parameters );

        handleCategoryDimension( sourceSharing, analyticalObject, listUpdateObjects, parameters );

        handleDataElementDimensions( sourceSharing, analyticalObject, listUpdateObjects, parameters );

        handleDataElementGroupSetDimensions( sourceSharing, analyticalObject, listUpdateObjects, parameters );

        handleCategoryOptionGroupSetDimensions( sourceSharing, analyticalObject, listUpdateObjects, parameters );

        handleTrackedEntityAttributeDimension( sourceSharing, analyticalObject, listUpdateObjects, parameters );
    }

    /**
     * Check if can merge sharing from given source to given analyticalObject's
     * {@link TrackedEntityAttributeDimension} and all related objects that has
     * Sharing enabled.
     *
     * @param sourceSharing {@link Sharing}
     * @param analyticalObject any object extends {@link BaseAnalyticalObject}
     * @param listUpdateObjects Set of objects need to be updated
     * @param parameters {@link CascadeSharingParameters}
     */
    private void handleTrackedEntityAttributeDimension( final Sharing sourceSharing,
        BaseAnalyticalObject analyticalObject,
        Set<IdentifiableObject> listUpdateObjects, CascadeSharingParameters parameters )
    {
        List<TrackedEntityAttributeDimension> attributeDimensions = analyticalObject
            .getAttributeDimensions();

        if ( CollectionUtils.isEmpty( attributeDimensions ) )
        {
            return;
        }

        attributeDimensions.forEach( attributeDimension -> {
            handleIdentifiableObject( sourceSharing, TrackedEntityAttribute.class, attributeDimension.getAttribute(),
                listUpdateObjects, parameters );
            handleIdentifiableObject( sourceSharing, LegendSet.class, attributeDimension.getLegendSet(),
                listUpdateObjects,
                parameters );
        } );
    }

    /**
     * Check if can merge sharing from given source to given analyticalObject's
     * {@link CategoryOptionGroupSetDimension} and all related objects that has
     * Sharing enabled.
     *
     * @param sourceSharing {@link Sharing}
     * @param analyticalObject any object extends {@link BaseAnalyticalObject}
     * @param listUpdateObjects Set of objects need to be updated
     * @param parameters {@link CascadeSharingParameters}
     */
    private void handleCategoryOptionGroupSetDimensions( final Sharing sourceSharing,
        BaseAnalyticalObject analyticalObject,
        Set<IdentifiableObject> listUpdateObjects, CascadeSharingParameters parameters )
    {
        List<CategoryOptionGroupSetDimension> catOptionGroupSetDimensions = analyticalObject
            .getCategoryOptionGroupSetDimensions();

        if ( CollectionUtils.isEmpty( catOptionGroupSetDimensions ) )
        {
            return;
        }

        catOptionGroupSetDimensions.forEach( categoryOptionGroupSetDimension -> {
            CategoryOptionGroupSet catOptionGroupSet = categoryOptionGroupSetDimension
                .getDimension();

            handleIdentifiableObject( sourceSharing, CategoryOptionGroupSet.class, catOptionGroupSet, listUpdateObjects,
                parameters );

            List<CategoryOptionGroup> catOptionGroups = catOptionGroupSet.getMembers();

            if ( CollectionUtils.isEmpty( catOptionGroups ) )
            {
                return;
            }

            catOptionGroups.forEach( catOptionGroup -> {
                handleIdentifiableObject( sourceSharing, CategoryOptionGroup.class, catOptionGroup, listUpdateObjects,
                    parameters );
                handleIdentifiableObjects( sourceSharing, CategoryOption.class, catOptionGroup.getMembers(),
                    listUpdateObjects,
                    parameters );
            } );

        } );
    }

    /**
     * Check if can merge sharing from given source to given analyticalObject's
     * {@link TrackedEntityDataElementDimension} and all related objects that
     * has Sharing enabled.
     *
     * @param sourceSharing {@link Sharing}
     * @param analyticalObject any object extends {@link BaseAnalyticalObject}
     * @param listUpdateObjects Set of objects need to be updated
     * @param parameters {@link CascadeSharingParameters}
     */
    private void handleDataElementDimensions( final Sharing sourceSharing, BaseAnalyticalObject analyticalObject,
        Set<IdentifiableObject> listUpdateObjects, CascadeSharingParameters parameters )
    {
        List<TrackedEntityDataElementDimension> deDimensions = analyticalObject
            .getDataElementDimensions();

        if ( CollectionUtils.isEmpty( deDimensions ) )
        {
            return;
        }

        deDimensions.forEach( deDimension -> {
            handleIdentifiableObject( sourceSharing, DataElement.class, deDimension.getDataElement(), listUpdateObjects,
                parameters );
            handleIdentifiableObject( sourceSharing, LegendSet.class, deDimension.getLegendSet(), listUpdateObjects,
                parameters );
            handleIdentifiableObject( sourceSharing, ProgramStage.class, deDimension.getProgramStage(),
                listUpdateObjects,
                parameters );
        } );
    }

    /**
     * Check if can merge sharing from given source to given analyticalObject's
     * {@link CategoryDimension} and all related objects that has Sharing
     * enabled.
     *
     * @param sourceSharing {@link Sharing}
     * @param analyticalObject any object extends {@link BaseAnalyticalObject}
     * @param listUpdateObjects Set of objects need to be updated
     * @param parameters {@link CascadeSharingParameters}
     */
    private void handleCategoryDimension( final Sharing sourceSharing, BaseAnalyticalObject analyticalObject,
        Set<IdentifiableObject> listUpdateObjects, CascadeSharingParameters parameters )
    {
        List<CategoryDimension> catDimensions = analyticalObject.getCategoryDimensions();

        if ( CollectionUtils.isEmpty( catDimensions ) )
        {
            return;
        }

        catDimensions.forEach( catDimension -> {
            Category category = catDimension.getDimension();

            handleIdentifiableObject( sourceSharing, Category.class, category, listUpdateObjects, parameters );

            List<CategoryOption> catOptions = catDimension.getItems();

            if ( CollectionUtils.isEmpty( catOptions ) )
            {
                return;
            }

            catOptions.forEach( catOption -> handleIdentifiableObject( sourceSharing, CategoryOption.class, catOption,
                listUpdateObjects, parameters ) );
        } );
    }

    /**
     * Check if can merge sharing from given source to given analyticalObject's
     * {@link DataElementGroupSetDimension} and all related objects that has
     * Sharing enabled.
     *
     * @param sourceSharing {@link Sharing}
     * @param analyticalObject any object extends {@link BaseAnalyticalObject}
     * @param listUpdateObjects Set of objects need to be updated
     * @param parameters {@link CascadeSharingParameters}
     */
    private void handleDataElementGroupSetDimensions( final Sharing sourceSharing,
        BaseAnalyticalObject analyticalObject,
        Set<IdentifiableObject> listUpdateObjects, CascadeSharingParameters parameters )
    {
        List<DataElementGroupSetDimension> deGroupSetDimensions = analyticalObject
            .getDataElementGroupSetDimensions();

        if ( CollectionUtils.isEmpty( deGroupSetDimensions ) )
        {
            return;
        }

        deGroupSetDimensions.forEach( deGroupSetDimension -> {
            DataElementGroupSet deGroupSet = deGroupSetDimension.getDimension();

            handleIdentifiableObject( sourceSharing, DataElementGroupSet.class, deGroupSet, listUpdateObjects,
                parameters );

            List<DataElementGroup> deGroups = deGroupSetDimension.getItems();

            if ( CollectionUtils.isEmpty( deGroups ) )
            {
                return;
            }

            deGroups
                .forEach( deGroup -> handleIdentifiableObject( sourceSharing, DataElementGroup.class, deGroup,
                    listUpdateObjects,
                    parameters ) );
        } );
    }

    /**
     * Check if each of target objects sharing can be merged from sourceSharing.
     * <p>
     * If yes then target object will be added to listUpdateObjects
     *
     * @param sourceSharing {@link Sharing}
     * @param targetObjects list of {@link IdentifiableObject}
     * @param listUpdateObjects Set of objects need to be updated.
     * @param parameters {@link CascadeSharingParameters}
     */
    private <T extends IdentifiableObject> void handleIdentifiableObjects( final Sharing sourceSharing, Class type,
        Collection<T> targetObjects,
        Collection<IdentifiableObject> listUpdateObjects,
        CascadeSharingParameters parameters )
    {
        if ( CollectionUtils.isEmpty( targetObjects ) )
        {
            return;
        }

        targetObjects.forEach(
            object -> handleIdentifiableObject( sourceSharing, type, object, listUpdateObjects, parameters ) );
    }

    /**
     * Check if target object's sharing can be merged from sourceSharing
     *
     * @param sourceSharing {@link Sharing}
     * @param target {@link IdentifiableObject}
     * @param listUpdateObjects Set of objects need to be updated.
     * @return TRUE if target object should be updated, otherwise return FALSE.
     */
    private <T extends IdentifiableObject> boolean handleIdentifiableObject( final Sharing sourceSharing, Class<T> type,
        T target,
        Collection<IdentifiableObject> listUpdateObjects,
        CascadeSharingParameters parameters )
    {
        if ( target == null )
        {
            return false;
        }

        T persistedTarget = manager.get( type, target.getUid() );

        if ( persistedTarget == null )
        {
            parameters.getReport().getErrorReports()
                .add( new ErrorReport( type, ErrorCode.E5001, target.getUid(), type.getSimpleName() ) );
            return false;
        }

        if ( canUserUpdate( persistedTarget, parameters ) && shouldUpdateSharing( sourceSharing, target ) )
        {
            listUpdateObjects.add( persistedTarget );
            return true;
        }

        return false;
    }

    /**
     * Check if given target's sharing need to be updated.
     *
     * @param source {@link Sharing}
     * @param target object to check
     * @return TRUE if object need update sharing, otherwise FALSE.
     */
    private <T extends IdentifiableObject> boolean shouldUpdateSharing( final Sharing source, final T target )
    {
        if ( AccessStringHelper.canRead( target.getSharing().getPublicAccess() ) )
        {
            return false;
        }

        if ( MapUtils.isEmpty( source.getUserGroups() ) && MapUtils.isEmpty( source.getUsers() ) )
        {
            return false;
        }

        return shouldUpdateAccessObjects( source.getUsers(), target.getSharing().getUsers() )
            || shouldUpdateAccessObjects( source.getUserGroups(), target.getSharing().getUserGroups() );
    }

    /**
     * Check if given target {@code Map<String,AccessObject>} need to be updated
     * based on given source {@code Map<String,AccessObject>}
     *
     * @return TRUE if one of AccessObject in target Map need to be updated,
     *         otherwise FALSE.
     */
    private <T extends AccessObject> boolean shouldUpdateAccessObjects( final Map<String, T> source,
        final Map<String, T> target )
    {
        if ( MapUtils.isEmpty( source ) )
        {
            return false;
        }

        boolean shouldUpdate = false;

        for ( final T sourceAccess : source.values() )
        {
            if ( !AccessStringHelper.canRead( sourceAccess.getAccess() ) )
            {
                continue;
            }

            T targetAccess = target.get( sourceAccess.getId() );

            if ( targetAccess != null && AccessStringHelper.canRead( targetAccess.getAccess() ) )
            {
                continue;
            }

            shouldUpdate = true;
        }

        return shouldUpdate;
    }

    /**
     * Add UserAccesses and UserGroupAccesses from source to target object.
     *
     * @return TRUE if targetObject is updated, otherwise return FALSE
     */
    private <T extends IdentifiableObject> boolean mergeSharing( final Sharing source, T target,
        CascadeSharingParameters parameters )
    {
        if ( mergeAccessObject( UserAccess.class, source.getUsers(), target.getSharing().getUsers() )
            || mergeAccessObject( UserGroupAccess.class, source.getUserGroups(), target.getSharing().getUserGroups() ) )
        {
            parameters.getReport().addUpdatedObject( getTypeReportKey( target ), target );
            return true;
        }

        return false;
    }

    /**
     * Add {@link AccessObject} from source to target
     * <p>
     * After added, target accessObjects will only have READ permission
     */
    private <T extends AccessObject> boolean mergeAccessObject( Class<T> type, final Map<String, T> source,
        Map<String, T> target )
    {
        if ( MapUtils.isEmpty( source ) )
        {
            return false;
        }

        boolean updated = false;

        for ( T sourceAccess : source.values() )
        {
            if ( !AccessStringHelper.canRead( sourceAccess.getAccess() ) )
            {
                continue;
            }

            T targetAccess = target.get( sourceAccess.getId() );

            if ( targetAccess != null && AccessStringHelper.canRead( targetAccess.getAccess() ) )
            {
                continue;
            }

            if ( targetAccess == null )
            {
                targetAccess = sourceAccess.copy();
            }

            targetAccess.setAccess( AccessStringHelper.READ );
            target.put( targetAccess.getId(), targetAccess );

            updated = true;
        }

        return updated;
    }

    /**
     * Get the plurals name of the object. Will be used to display list updated
     * objects in the {@link CascadeSharingReport}
     *
     * @return plurals name of the object schema.
     */
    private String getTypeReportKey( Object object )
    {
        return schemaService.getDynamicSchema( HibernateProxyUtils.getRealClass( object ) ).getPlural();
    }

    /**
     * Check if currentUser can update given object, if not add new ErrorReport
     * to {@link CascadeSharingParameters}.
     *
     * @param object object for validating
     * @param parameters {@link CascadeSharingParameters}
     * @return TRUE if current user can update given object, otherwise FALSE.
     */
    private <T extends IdentifiableObject> boolean canUserUpdate( T object, CascadeSharingParameters parameters )
    {
        if ( !aclService.canUpdate( parameters.getUser(), object ) )
        {
            parameters.getReport().getErrorReports().add( new ErrorReport( HibernateProxyUtils.getRealClass( object ),
                ErrorCode.E3001, parameters.getUser().getUsername(), object.getUid() ) );
            return false;
        }

        return true;
    }
}


text:
package ecd

//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//
// Code generated by Alibaba Cloud SDK Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.

// Invocation is a nested struct in ecd response
type Invocation struct {
	InvokeId         string          `json:"InvokeId" xml:"InvokeId"`
	CommandContent   string          `json:"CommandContent" xml:"CommandContent"`
	CommandType      string          `json:"CommandType" xml:"CommandType"`
	InvocationStatus string          `json:"InvocationStatus" xml:"InvocationStatus"`
	CreationTime     string          `json:"CreationTime" xml:"CreationTime"`
	EndUserId        string          `json:"EndUserId" xml:"EndUserId"`
	InvokeDesktops   []InvokeDesktop `json:"InvokeDesktops" xml:"InvokeDesktops"`
}


text:
/**
 *    @file
 *          Example project configuration file for CHIP.
 *
 *          This is a place to put application or project-specific overrides
 *          to the default configuration values for general CHIP features.
 *
 */

#pragma once

// Use a default setup PIN code if one hasn't been provisioned in flash.
#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00

// For convenience, enable Chip Security Test Mode and disable the requirement for
// authentication in various protocols.
//
//    WARNING: These options make it possible to circumvent basic Chip security functionality,
//    including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS.
//
#define CHIP_CONFIG_SECURITY_TEST_MODE 0

/**
 * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
 *
 * 0xFFF1: Test vendor.
 */
#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1

/**
 * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
 *
 * 0x8009: example persistent-storage
 */
#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8009

/**
 * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION
 *
 * The hardware version number assigned to device or product by the device vendor.  This
 * number is scoped to the device product id, and typically corresponds to a revision of the
 * physical device, a change to its packaging, and/or a change to its marketing presentation.
 * This value is generally *not* incremented for device software versions.
 */
#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 1

/**
 * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
 *
 * A string identifying the software version running on the device.
 * CHIP service currently expects the software version to be in the format
 * {MAJOR_VERSION}.0d{MINOR_VERSION}
 */
#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "0.1ALPHA"
#endif
/**
 * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
 *
 * Enable support for Chip-over-BLE (CHIPoBLE).
 */
#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1

/**
 * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC
 *
 * Enables synchronizing the device's real time clock with a remote Chip Time service
 * using the Chip Time Sync protocol.
 */
#define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 0

/**
 * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
 *
 * Enables the use of a hard-coded default serial number if none
 * is found in Chip NV storage.
 */
#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN"

/**
 * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE
 *
 * A size, in bytes, of the individual debug event logging buffer.
 */
#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512)

/**
 * CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI
 *
 * Enable Thread CLI interface at initialisation.
 */
#define CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI 1

/**
 *  @def CHIP_CONFIG_MAX_FABRICS
 *
 *  @brief
 *    Maximum number of fabrics the device can participate in.  Each fabric can
 *    provision the device with its unique operational credentials and manage
 *    its own access control lists.
 */
#define CHIP_CONFIG_MAX_FABRICS 4 // 3 fabrics + 1 for rotation slack

/**
 *  @name Interaction Model object pool configuration.
 *
 *  @brief
 *    The following definitions sets the maximum number of corresponding interaction model object pool size.
 *
 *      * #CHIP_IM_MAX_NUM_COMMAND_HANDLER
 *      * #CHIP_IM_MAX_REPORTS_IN_FLIGHT
 *      * #CHIP_IM_MAX_NUM_WRITE_HANDLER
 *      * #CHIP_IM_MAX_NUM_WRITE_CLIENT
 *
 *  @{
 */

/**
 * @def CHIP_IM_MAX_NUM_COMMAND_HANDLER
 *
 * @brief Defines the maximum number of CommandHandler, limits the number of active commands transactions on server.
 */
#define CHIP_IM_MAX_NUM_COMMAND_HANDLER 2

/**
 * @def CHIP_IM_MAX_REPORTS_IN_FLIGHT
 *
 * @brief Defines the maximum number of Reports, limits the traffic of read and subscription transactions.
 */
#define CHIP_IM_MAX_REPORTS_IN_FLIGHT 2

/**
 * @def CHIP_IM_MAX_NUM_WRITE_HANDLER
 *
 * @brief Defines the maximum number of WriteHandler, limits the number of active write transactions on server.
 */
#define CHIP_IM_MAX_NUM_WRITE_HANDLER 2

/**
 * @def CHIP_IM_MAX_NUM_WRITE_CLIENT
 *
 * @brief Defines the maximum number of WriteClient, limits the number of active write transactions on client.
 */
#define CHIP_IM_MAX_NUM_WRITE_CLIENT 2


text:
(note this is just an outline in readme form.  there is no code yet)

# FormTransporter

Create a form, including sections and validations, and transport it to another app/database.

A form is an ordered list of labels, form fields, types and validations.  A submitted form is the answered form.

## Usage

#### Create Form

```ruby
transport_form = TransportForm.new(name: "My Required Contact Form")
transport_form.lines << Section.new(description: "Contact info")  # just a descriptive element
transport_form.lines << TFString.new(name: "first_name", required:true)
transport_form.lines << TFCheckbox.new(name: "")
...
transport_form.save
```

#### Transport the form (ship form to another system for answering)

```ruby
transport_form.serialize
```

(ship it off to another place.  perhaps via rest-api)

#### Get an Answer
``` ruby
@tf = TransportForm.deserialize
@tf.save
```

__in a view__
```ruby
@tf.render
```

__then in the transported form controller__
```ruby
tfa = TransportFormAnswer.new params[:form]
tfa.save # validation also happens, re-render on failures
```

#### Return Transport (ship back answer to originating system)

```ruby
tfa.serialize
```

And the answer(s) are associated with the original form.


text:
<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="exo_media_action_repeat_off_description">Nu repetați niciunul</string>
  <string name="exo_media_action_repeat_one_description">Repetați unul</string>
  <string name="exo_media_action_repeat_all_description">Repetați-le pe toate</string>
</resources>


text:
<?php
declare(strict_types = 1);
/**
 * /tests/Integration/Integration/LogRequestRepositoryTest.php
 *
 * @author TLe, Tarmo Leppänen <tarmo.leppanen@protacon.com>
 */

namespace App\Tests\Integration\Repository;

use App\Entity\Interfaces\EntityInterface;
use App\Entity\LogRequest;
use App\Repository\Interfaces\BaseRepositoryInterface;
use App\Repository\LogRequestRepository;
use App\Resource\LogRequestResource;
use App\Rest\Interfaces\RestResourceInterface;

/**
 * Class LogRequestRepositoryTest
 *
 * @package App\Tests\Integration\Repository
 * @author TLe, Tarmo Leppänen <tarmo.leppanen@protacon.com>
 *
 * @method LogRequestResource getResource()
 * @method LogRequestRepository getRepository()
 */
class LogRequestRepositoryTest extends RepositoryTestCase
{
    /**
     * @var class-string<EntityInterface>
     */
    protected string $entityName = LogRequest::class;

    /**
     * @var class-string<BaseRepositoryInterface>
     */
    protected string $repositoryName = LogRequestRepository::class;

    /**
     * @var class-string<RestResourceInterface>
     */
    protected string $resourceName = LogRequestResource::class;

    /**
     * @var array<int, string>
     */
    protected array $associations = [
        'user',
        'apiKey',
    ];
}


text:
module Focus where

import qualified XMonad.StackSet as W
import qualified XMonad.Util.ExtensibleState as State
import Imports

data WorkspaceSwitchLock = SwitchingNotLocked | SwitchingLocked
  deriving (Eq, Ord, Enum, Bounded, Read, Show, Typeable)

instance ExtensionClass WorkspaceSwitchLock where
  initialValue = SwitchingNotLocked
  extensionType = PersistentExtension

focusWorkspace :: String -> XX ()
focusWorkspace workspaceName = do
  x <- toXX $ State.get
  case x of
    SwitchingNotLocked -> toXX $ windows (W.greedyView workspaceName)
    SwitchingLocked -> spawn "notify-send" ["-t", "1000", "FOCUS!"]

lockWorkspaceSwitching :: XX ()
lockWorkspaceSwitching = toXX $ State.put SwitchingLocked

unlockWorkspaceSwitching :: XX ()
unlockWorkspaceSwitching = toXX $ State.put SwitchingNotLocked