Policy enforcement to add a new item - ASPECTJ - aop

I have to enforce a policy issuing a warning if items not belonging to a particular category are being added, apart from the three which are allowed and disallowing such additions.....
So far i am able to find the items and issue warning.... but not sure how to stop them from being added.... For Eg.
Allowed categories Shoes and socks
but if i try and add a vegetable item to the inventory it should give me a warning saying "category not allowed../nItem will not be added to inventory"..... and then proceed to the next item....
This is what i've written so far.....
import org.aspectj.lang.*;
public aspect a8 {
boolean check;
pointcut deliverMessage(): call(* ShoppingCart.addItem(..));
pointcut interestingcalls(String categorie): call(Item.new(..)) && args(*, *, categorie);
before(String categorie): interestingcalls(categorie)
{
if(categorie.equals("Shoes"))
{
System.out.println("categorie detect:" +categorie);
}
else if(categorie.equals("socks"))
{
System.out.println("categorie detect:" +categorie);
}
else
{
check=true;
around(categorie);
System.out.println("please check categorie" +categorie);
}
}
around(String categorie): interestingcalls(categorie) {
System.out.println("Start! "+categorie);
proceed(categorie);
System.out.println("End!");
}
}
I know i'm not using the around advice correctly....

What you probabily want is comething like this:
public aspect CartAspect {
pointcut checkAdd(String categorie) : call (void ShoppingCart.addItem(*)) && args(categorie);
void around(String categorie) : checkAdd(categorie) {
System.out.println("Start! " + categorie);
if (categorie.equals("shoes")) {
System.out.println("categorie detect:" + categorie);
proceed(categorie);
} else if (categorie.equals("socks")) {
System.out.println("categorie detect:" + categorie);
proceed(categorie);
} else {
System.out.println("please check categorie " + categorie);
}
System.out.println("End!");
}
}
Notice that in the case that the category is different from "shoes" or "socks", we DON'T call the proceed() method.

Related

How to get Flux-Results into a set of a Mono-Bean

I have the following scenario: I have a ProductFamily that has a set of Products.
I load the ProduktFamily from the database and then I want to load its Products and insert them into ProduktFamily.products.
Easy in Spring MVC (because of JPA) but with Webflux I am struggeling.
I tried this, but it does not work. ProduktFamily.products-set is empty.
Service:
public Flux<ProduktfamilyRS> getAllProduktFamilies() {
return produktfamilyDatabaseFacade.findAll()
.map(produktfamilyEntity2 -> dtoMapper.produktfamilyEntityToProduktfamilyRS(produktfamilyEntity2)) // <-- Mapsctruct Mapper
.concatMap(produktfamilyRS -> loadProducts(produktfamilyRS));
}
private Mono<ProduktfamilieRS> loadProducts(ProduktfamilieRS produktfamilieRS) {
Flux<ProduktEntity> byProduktfamilieId = produktDatabaseFacade.findByProduktfamilieId(produktfamilieRS.getId());
Flux<ProduktRS> produktRSFlux = byProduktfamilieId.map(produktEntity -> dtoMapper.produktEntityToProduktRS(produktEntity));
return Mono.just(produktfamilieRS).map(produktfamilieRS1 -> {
produktRSFlux.all(produktRS -> produktfamilieRS1.getProdukte().add(produktRS));
produktRSFlux.subscribe();
return produktfamilieRS1;
});
}
ProduktfamilyDatabaseFacade:
public Flux<ProduktfamilyEntity> findAll() {
return produktfamilyRepository.findAll();
}
ProduktfamilyDatabaseFacade:
public Flux<ProduktEntity> findByProduktfamilyId(Long produktfamilyId) {
return produktRepository.findAllByProduktfamilyId(produktfamilyeId)
.doOnNext(produktEntity -> log.info("Found Produkt '" + produktEntity.getName() + "' für Produktfamilie"));
}
Is there an way to start from the Mono and then iterate through the Flux to add every Product to the Productfamily and then return the ProductfamilyRS?
Thank you
Ok got it working, but do not know if its a good way. Can somebody review?
public Flux<ProduktfamilieRS> getAllProduktFamilien() {
return produktfamilieDatabaseFacade.findAll()
.map(produktfamilieEntity2 -> dtoMapper.produktfamilieEntityToProduktfamilieRS(produktfamilieEntity2))
.concatMap(this::loadProdukteFlat);
}
private Mono<ProduktfamilieRS> loadProdukteFlat(ProduktfamilieRS produktfamilieRS) {
return produktDatabaseFacade.findByProduktfamilieId(produktfamilieRS.getId())
.doOnNext(produktEntity -> produktfamilieRS.getProdukte().add(dtoMapper.produktEntityToProduktRS(produktEntity)))
.then(Mono.just(produktfamilieRS));
}

How does WorldEdit handle brushes?

I'm trying to find out how the Bukkit version of WorldEdit handles brushes. I've been looking at the source code on GitHub, but I couldn't find anythig useful. I've tried to recreate the effect, but I can only get it to work when I'm in interaction reach of the target block.
This is about as close as it gets in the source code:
} else if (action == Action.RIGHT_CLICK_AIR) {
if (we.handleRightClick(player)) {
event.setCancelled(true);
}
}
(WorldEdit/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditListener.java, line 143-147)
There are some other parts of code that get very close. I've also looked in /worldedit-core, but nothing there either.
Could someone help me here?
Edit: This is how I try to do it:
public static void onRightClick (PlayerInteractEvent event) {
if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
Location location = event.getClickedBlock().getLocation();
if (event.getItem() != null) {
if (event.getItem().getItemMeta().equals(ItemManager.wand.getItemMeta())) {
Player player = event.getPlayer();
player.getWorld().doStuff(location);
}
}
}
}
Edit #2: what I'm most curious about is: How does WE select the location to apply the brush if you are outside of interaction reach?
I needed to use BlockIterators for this. The final code looks like this:
public class BoomWandEvent implements Listener {
#EventHandler
public static void onRightClick (PlayerInteractEvent event) {
Player player = event.getPlayer();
if (event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.RIGHT_CLICK_AIR) {
if (player.getInventory().getItemInMainHand().equals(ItemManager.explosionWand)) {
Location eyePos = player.getEyeLocation();
BlockIterator raytracer = new BlockIterator(eyePos, 0.0D, player.getClientViewDistance() * 16);
while (raytracer.hasNext()) {
Location location = raytracer.next().getLocation();
if (player.getWorld().getBlockAt(location).getType() != Material.AIR && player.getWorld().getBlockAt(location).getType() != Material.CAVE_AIR && player.getWorld().getBlockAt(location).getType() != Material.VOID_AIR) {
player.getWorld().createExplosion(location, 4f);
return;
}
}
}
}
}
}
Thanks to Rogue for helping!

Is Sylius PayumBundle handling payment details incorrectly?

I am testing Bitbag/PayUPlugin and I was stopped by gateway API with error "Required data missing".
After some debugging, I realised that Sylius Payment entity, specifically "details" property, is not fulfilled with data.
After change condition on line 53:
https://github.com/Sylius/Sylius/blob/4e06a4dfb8dc56731470016bb97165f3025947b7/src/Sylius/Bundle/PayumBundle/Action/CapturePaymentAction.php#L53
to
if ($status->isNew() || $status->isUnknown()) {
payment gateway seems to work correctly.
Is it a bug or am I doing something wrong ?
Sylius/Sylius v1.4.6
Bitbag/PayUPlugin v1.8.0
Unlikely there is an error in PayumBundle/CapturePaymentAction (because more people used PayumBundle than PayUPlugin, so probability of bug is less), conceptually payment object status at the beginning should be "new" instead of "unknown", so the condition should work.
So you should find out https://github.com/BitBagCommerce/SyliusPayUPlugin/blob/master/src/Action/StatusAction.php#L58 class, why it doesn't reach markNew() line.
I guess the BitBagCommerce/SyliusPayUPlugin is dead as this issue hasn't been addressed yet, since July.
In order to fix this I had to decorate the StatusAction class:
<?php
declare(strict_types=1);
namespace App\Payment\PayU;
use BitBag\SyliusPayUPlugin\Action\StatusAction;
use BitBag\SyliusPayUPlugin\Bridge\OpenPayUBridgeInterface;
use Payum\Core\Action\ActionInterface;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\Request\GetStatusInterface;
final class StatusActionDecorator implements ActionInterface
{
private $action;
public function __construct(StatusAction $action)
{
$this->action = $action;
}
public function setApi($api): void
{
$this->action->setApi($api);
}
public function execute($request): void
{
/** #var $request GetStatusInterface */
RequestNotSupportedException::assertSupports($this, $request);
$model = ArrayObject::ensureArrayObject($request->getModel());
$status = $model['statusPayU'] ?? null;
if (empty($status) || OpenPayUBridgeInterface::NEW_API_STATUS === $status) {
$request->markNew();
return;
}
if (OpenPayUBridgeInterface::PENDING_API_STATUS === $status) {
$request->markPending();
return;
}
if (OpenPayUBridgeInterface::CANCELED_API_STATUS === $status) {
$request->markCanceled();
return;
}
if (OpenPayUBridgeInterface::WAITING_FOR_CONFIRMATION_PAYMENT_STATUS === $status) {
$request->markSuspended();
return;
}
if (OpenPayUBridgeInterface::COMPLETED_API_STATUS === $status) {
$request->markCaptured();
return;
}
$request->markUnknown();
}
public function supports($request): bool
{
return $this->action->supports($request);
}
}
then in the services.yaml:
App\Payment\PayU\StatusActionDecorator:
decorates: bitbag.payu_plugin.action.status
arguments: ['#App\Payment\PayU\StatusActionDecorator.inner']

How to return object from retrofit api get call

I am trying to get list of objects from api call with retrofit but i just cant find the way to do so :(
This is the function i built:
private List<Business> businesses getBusinesses()
{
List<Business> businessesList = new ArrayList<>();
Call<List<Business>> call = jsonPlaceHolderApi.getBusinesses();
call.enqueue(new Callback<List<Business>>() {
#Override
public void onResponse(Call<List<Business>> call, Response<List<Business>> response) {
if(!response.isSuccessful())
{
textViewResult.setText("Code: " + response.code());
return;
}
List<Business> businesses = response.body();
for(Business business : businesses)
{
String content = "";
content += "ID: " + business.getId() + "\n";
content += "Name: " + business.getName() + "\n";
content += "On promotion: " + business.isOnPromotion() + "\n\n";
textViewResult.append(content);
}
businessesList = businesses;
}
#Override
public void onFailure(Call<List<Business>> call, Throwable t) {
call.cancel();
textViewResult.setText(t.getMessage());
}
});
}
I am trying to get the businesses response and return it.
can anyone help me?
Feeling frustrated :(
The way your executing the Retrofit call is asynchronous - using call.enqueue. there's nothing wrong with this approach. In fact it's perhaps the best option, since network calls can take a while and you don't want to block unnecessarily.
Unfortunately, this means you cannot return the result from the function. In most scenarios, if you did, the call would likely finish after the return making your return useless.
There are several ways to deal with this, the simplest one is to use callbacks. For example:
interface OnBusinessListReceivedCallback {
void onBusinessListReceived(List<Business> list);
}
private void businesses getBusinesses(OnBusinessListReceivedCallback callback){
Call<List<Business>> call = jsonPlaceHolderApi.getBusinesses();
call.enqueue(new Callback<List<Business>>() {
#Override
public void onResponse(Call<List<Business>> call, Response<List<Business>> response) {
if(!response.isSuccessful()){
textViewResult.setText("Code: " + response.code());
return;
}
callback.onBusinessListReceived(response.body());
}
#Override
public void onFailure(Call<List<Business>> call, Throwable t) {
call.cancel();
textViewResult.setText(t.getMessage());
}
});
}
You can then call it like so:
getBusinesses(new OnBusinessListReceivedCallback() {
public void onBusinessListReceived(List<Business> list){
// list holds your data
}
});

Set default combination automaticly based on stock Prestashop 1.7

i need Prestashop to:
Check stock of combinations from a product.
If a combination is out of stock, set default combination to a different combination which is in stock.
This way the shop will not show : 'out of stock' at the product, on the category listing. Makes no sense, because the product is not out of stock, only 1 combination is out of stock.
Another solution will be: the out of stock sticker to check if there are any combinations in stock.
Please do not advise any modules.
Example given:
T-shirt in size Small, Medium and Large.
Small: 0 stock, Medium: 10 stock, Large: 10 stock.
Prestashop will now show T-shirt as out of stock on the frontend, unless i manually check Medium or Large as a default size.
You will need to modify ProductController(/controllers/front/ProductController.php)
Basically what i did was to check if the default attribute has stock. If there is stock,then there is no need to look else where.
If there is no stock, then get all the product attributes and loop through the attributes. Once attribute with stock is found, delete the old default attribute and set the found as default attribute.
Add this methods inside the productController Class
/*
start set default based on stock
*/
public function getProductAttributes()
{
$sql = "SELECT * FROM " . _DB_PREFIX_ . "product_attribute WHERE
id_product = ". (int) $this->product->id;
return Db::getInstance()->executeS($sql);
}
public function getProductStock($id_product_attribute)
{
return StockAvailable::getQuantityAvailableByProduct($this->product->id,
$id_product_attribute, $this->context->shop->id);
}
public function checkDefault()
{
$id_product_attribute = Product::getDefaultAttribute($this->product->id);
$stk = (int) $this->getProductStock($id_product_attribute);
if( $stk > 0){
return true;
}
return false;
}
public function checkAttributeStock( $id_product_attribute)
{
$stk = $this->getProductStock($id_product_attribute);
if( $stk > 0){
return true;
}
return false;
}
public function setDefaultBasedOnStock()
{
if($this->checkDefault()){
return true;
}
$product_atts = $this->getProductAttributes();
if(count($product_atts) >0){
foreach($product_atts as $attri){
if($this->checkAttributeStock($attri['id_product_attribute'])){
$this->product->deleteDefaultAttributes();
$this->product->setDefaultAttribute($attri['id_product_attribute']);
break;
}
}
}
}
/*
end set default based on stock
*/
Then you need to call setDefaultBasedOnStock method inside init Method just after parent::init();
public function init()
{
parent::init();
$this->setDefaultBasedOnStock();
// here is the rest of init code ......
//Do not delete the rest of init code
}
Please do not delete the rest of init() method code, just add this line $this->setDefaultBasedOnStock(); below parent::init();
The best way will be to override productController
Instead of modifying productController class, you can create productController override class inside /override/controllers/front/ folder
class ProductController extends ProductControllerCore {
// add all the methods above
// including the init method
}
// After add override you may need to clear cache if prestashop cache is enabled.