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.....
pointcut deliverMessage() :
call(* SC.addItem(..));
pointcut interestingCalls(String category) :
call(Item.new(..)) && args(*, *, category);
before(String category): interestingCalls(category) {
if(category.equals("Socks")) {
System.out.println("category detect: " + category);
else if(category.equals("Shoes"))
System.out.println("category detect: " + category);
else {
check=true;
System.out.println("please check category " + category);
}
}
Why not use the around aspect instead. Then, if they are not of the correct category you don't go into that method, so it gets skipped, if the skipped method is just doing the adding.
UPDATE:
Here is an example from AspectJ In Action, by Manning Publication.
public aspect ProfilingAspect {
pointcut publicOperation() : execution(public * *.*(..));
Object around() : publicOperation() {
long start = System.nanoTime();
Object ret = proceed();
long end = System.nanoTime();
System.out.println(thisJoinPointStaticPart.getSignature()
+ " took " + (end-start) + " nanoseconds");
return ret;
}
}
So, if you wanted to check if you should add the item, if it is an allowed category then just call proceed, otherwise you would just return a null perhaps.
Related
I want to delete many managed objects, selected by fragment type. There are more then 2000 elements in it. Unfortunately I can not delete all with one function call. I have to call this function many times until I have deleted all. How can I delete a list of managed objects in a sufficient way? Not defining page size did not help...
This is my current function:
InventoryFilter filter = new InventoryFilter();
filter.byFragmentType("xy_fragment");
ManagedObjectCollection moc = inventoryApi.getManagedObjectsByFilter(filter);
int count = 0;
// max page size is 2000
for (ManagedObjectRepresentation mo : moc.get(2000).allPages()) {
if (mo.get("c8y_IsBinary") != null) {
binariesApi.deleteFile(mo.getId());
} else {
inventoryApi.delete(mo.getId());
}
LOG.debug(count + " remove: " + mo.getName() + ", " + mo.getType());
count++;
}
LOG.info("all objectes removed, count:" + count);
By calling moc.get(2000).allPages() you already obtain an iterator that queries following pages on demand as you iterate over it.
The problem you are facing is caused by deleting elements from the same list you are iterating over. You delete element from the first page, but once the second page is queried from the server it does not contain the expected elements anymore because you already deleted the first page. Now all elements are shifted forward by your page size.
You can avoid all of that by making a local copy of all elements you want to delete first:
List<ManagedObjectRepresentation> allObjects = Lists.newArrayList( moc.get(2000).allPages())
for (ManagedObjectRepresentation mo : allObjects) {
//delete here
}
There is no bulk delete allowed on the inventory API so your method of looping through the objects is the correct approach.
A bulk delete is already a dangerous tool on the other APIs but on the inventory API it would give you the potential to accidentally delete all your data with just one call (as all data associated with a managedObject is also deleted upon the deletion of the managedObject).
That is why it is not available.
I solved the problem by calling the method until no elements can be found any more. It is not nice but I have no other idea.
public synchronized void removeManagedObjects(String deviceTypeKey) {
int count = 0;
do {
count = deleteManagedObjectes(deviceTypeKey);
}while(count > 0);
}
private int deleteManagedObjectes(String deviceTypeKey) {
InventoryFilter filter = new InventoryFilter();
filter.byFragmentType("xy_fragment");
ManagedObjectCollection moc = inventoryApi.getManagedObjectsByFilter(filter);
int count = 0;
if(moc == null) {
LOG.info("ManagedObjectCollection are NULL");
return count;
}
for (ManagedObjectRepresentation mo : moc.get(2000).allPages()) {
if (mo.get("c8y_IsBinary") != null) {
binariesApi.deleteFile(mo.getId());
} else {
inventoryApi.delete(mo.getId());
}
LOG.debug(count + " remove: " + mo.getName() + ", " + mo.getType());
count++;
}
LOG.info("all objectes removed, count:" + count);
return count;
}
I'm new to Spock and this question refers to the example on page 178 of Java Testing with Spock. The class under test is the Basket class for a shopping application, and the method of this class being tested is canShipCompletely()
public class Basket {
private WarehouseIneventory warehouseInventory;
private ShippingCalculator shippingCalculator;
protected Map<Product, Integer> contents = new HashMap<>();
...
public void addProduct(Product product) {
addProduct(product, 1);
}
public void addProduct(Product product, int times) {
if (contents.containsKey(product)) {
int existing = contents.get(product);
contents.put(product, existing + times);
} else {
contents.put(product, times);
}
}
public Boolean canshipCompletely() {
if(warehouseInventory.isEmpty()) return false;
try {
for (Entry<Product, Integer> entry : contents.entrySet())
boolean ok = warehouseInventory.isProductAvailable(
entry.getKey().getName(),
entry.getValue()
);
if (!ok) {
return false;
}
}
return true;
} catch (Exception e) {
return false;
}
...
}
This method canShipCompletely() loops over the items in the basket (in Map contents) and for each item, it makes a call to warehouseInventory.isProductAvailable(product, count) to see if there is sufficient stock in the warehouse to fill the order. The Warehouse class is a collaborator of the Basket class that is mocked in the following test
def "Warehouse is queried for each product"() {
given: "a basket, a TV and a camera"
Product tv = new Product(name:"bravia",price:1200,weight:18)
Product camera = new Product(name:"panasonic",price:350,weight:2)
Basket basket = new Basket()
and: "a warehouse with limitless stock"
WarehouseInventory inventory = Mock(WarehouseInventory)
basket.setWarehouseInventory(inventory)
when: "user checks out two products"
basket.addProduct tv
basket.addProduct camera
boolean readyToShip = basket.canShipCompletely()
then: "order can be shipped"
readyToShip
2 * inventory.isProductAvailable( _ , _) >> true
0 * inventory.preload(_ , _)
}
The then: block verifies the boolean readyToShip is true, and that inventory.isProducAvailable() was called twice and inventory.preload() was not called at all. The next to last line is both checking behavior of the mock and telling it to return true for calls to isProductAvailable(). What I don't understand is the test will fail if I move the mock predefined response to the and: block as follows
def "Warehouse is queried for each product"() {
given: "a basket, a TV and a camera"
Product tv = new Product(name:"bravia",price:1200,weight:18)
Product camera = new Product(name:"panasonic",price:350,weight:2)
Basket basket = new Basket()
and: "a warehouse with limitless stock"
WarehouseInventory inventory = Mock(WarehouseInventory)
// ******** Move mock predefined response here **********
inventory.isProductAvailable( _ , _ ) >> true
basket.setWarehouseInventory(inventory)
when: "user checks out two products"
basket.addProduct tv
basket.addProduct camera
boolean readyToShip = basket.canShipCompletely()
then: "order can be shipped"
readyToShip
2 * inventory.isProductAvailable( _ , _)
0 * inventory.preload(_ , _)
}
The failure I get is too few calls to isProductAvailable():
Too few invocations for:
2 * inventory.isProductAvailable( _ , _) (1 invocation)
Unmatched invocations (ordered by similarity):
1 * inventory.isEmpty()
I don't understand why the predefined behavior for the mock can't be moved to the and: block.
Please refer to the documentation
When mocking and stubbing the same method call, they have to happen in the same interaction. In particular, the following Mockito-style splitting of stubbing and mocking into two separate statements will not work:
setup:
subscriber.receive("message1") >> "ok"
when:
publisher.send("message1")
then:
1 * subscriber.receive("message1")
As explained in Where to Declare Interactions, the receive call will first get matched against the interaction in the then: block. Since that interaction doesn’t specify a response, the default value for the method’s return type (null in this case) will be returned. (This is just another facet of Spock’s lenient approach to mocking.). Hence, the interaction in the setup: block will never get a chance to match.
Is there any way to programmatically understand what properties there are for a custom model in Alfresco?
For example, data dictionary in oracle helps you to find what tables are defined by which column names and column data types.
My goal is a sample code in java which extracts all custom defined content models, their attributes, their attributes data types, etc. For example my sample code should return to me that there is a custom content Model which has an integer attribute with name 'No' and a string attribute with name 'Description'. I know this is possible with DictionaryComponent, But I don't know how should I use it.
Take a look at org.alfresco.service.cmr.dictionary.DictionaryService.
will your Java-code running in-context with alfresco (as part of the /alfresco webapp) or outside?
If your running in-context, then Alfreso Java Foundation API is your choice where DictionaryService is part of. just inject the bean into your java code.
If your code is running outside of alfresco, then Alfresco REST API or CMIS is your choice.
If you're still lost, then train yourself first. Jeff wrote some good articles http://ecmarchitect.com/alfresco-developer-series & also a book.
Also a good starting point - Alfresco Developer Docs: http://docs.alfresco.com/4.2/topic/com.alfresco.enterprise.doc/concepts/dev-for-developers.html
thanks a lot of alfresian responses, My code sample is something like below:
I found the sample code from : this URL
public void GetAllAvailableDataTypes() throws IOException
{
Session session = getSession();
boolean includePropertyDefintions = true;
for (Tree t : session.getTypeDescendants(
null, // start at the top of the tree
-1, // infinite depth recursion
includePropertyDefintions // include prop defs
)) {
printTypes(t, "");
}
}
public void printTypes(Tree tree, String tab) {
ObjectType objType = (ObjectType) tree.getItem();
String type = objType.getId();
if(true)//type.endsWith("hstcase"))
{
System.out.println(tab + "TYPE:" + objType.getDisplayName() +
" (" + objType.getDescription() + ")");
//Print some of the common attributes for this type
System.out.print(tab + " Id:" + "-----"+ objType.getId() + "-----");
System.out.print(" Fileable:" + objType.isFileable());
System.out.print(" Queryable:" + objType.isQueryable());
if (objType instanceof DocumentType) {
System.out.print(" [DOC Attrs->] Versionable:" +
((DocumentType)objType).isVersionable());
System.out.println(" Content:" +
((DocumentType)objType).getContentStreamAllowed());
Map<String, org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition<?>> props = objType.getPropertyDefinitions();
Set<String> keys = props.keySet();
Collection<org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition<?>> porpsAsCollection = props.values();
for(org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition<?> p: porpsAsCollection)
{
//System.out.println(p.getDescription());
PropertyType pt = p.getPropertyType();
System.out.println("Display Name: "+ p.getDisplayName());
System.out.println("Local Name: "+ p.getLocalName());
System.out.println("Attribute Type: "+ pt.value());
}
}
System.out.println(""); // end the line
}
List<Tree> childs = tree.getChildren();
for (Tree t : childs) {
// there are more - call self for next level
printTypes(t, tab + " ");
}
}
I have a taxonomy index that describes a tree structure. When performing a query I want to get the number of hits for multiple categories (not necessarily in the same level of the tree). For example, given the following list of paths:
[Root/Cat1, Root/Cat1/Cat12, Root/Cat3]
I want to obtain the number of hits for each of these three categories.
I've been looking for a solution and I know that is possible to make a tree request and then get the results by calling .getSubResults() (as it is explained in the API). However I haven't found any example and I don't really know how to implement it. So far I've got to the following:
// Build query
Query query = extendQuery(queryGenerator.generateQuery(resource));
// Set the number of top results
TopScoreDocCollector tdc = TopScoreDocCollector.create(numTopDocuments, true);
// Set a faceted search
FacetSearchParams facetSearchParams = new FacetSearchParams();
// Search at level of the category in interests
CountFacetRequest facetRequest = new CountFacetRequest(new CategoryPath("Top", '/'), numTopCategories);
facetRequest.setResultMode(ResultMode.PER_NODE_IN_TREE);
facetSearchParams.addFacetRequest(facetRequest);
// To collect the number of hits per facet
FacetsCollector facetsCollector =
new FacetsCollector(facetSearchParams, documentReader, taxonomyReader);
try {
// Collect the number of hits per facet
documentSearcher
.search(query, MultiCollector.wrap(tdc, facetsCollector));
for (FacetResult res : facetsCollector.getFacetResults()){
//this is the top lvl facet
FacetResultNode toplvl = res.getFacetResultNode();
System.out.println(toplvl.getLabel() + " (" + toplvl.getValue() + ")");
for (FacetResultNode secondlvl : toplvl.getSubResults()) {
//second lvl facet categories
System.out.println(" " + secondlvl.getLabel().getComponent(1)
+ " (" + secondlvl.getValue() + ")");
for (FacetResultNode thirdlvl : secondlvl.getSubResults()) {
//second lvl facet categories
System.out.println(" " + thirdlvl.getLabel().getComponent(2)
+ " (" + thirdlvl.getValue() + ")");
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
However, when I get to the third level I get null. What is going on?
Thanks.
You have to set also:
facetRequest.setDepth(MAX_DEPTH_TREE);
numberrange returns [String value]
: numberrangesub
{
String numberRange = ($numberrangesub.text);
String [] v = numberRange.split(",");
if ( Integer.parseInt(v[0].trim()) < Integer.parseInt(v[1].trim())) $value =numberRange;
else throw new RecognitionException();
}
;
Please observe the above ANTLR code. In this I want to throw a user friendly error message like "from value should be less than to value in BETWEEN clause".
I am expecting like this RecognitionException("from value should be less than to value in BETWEEN clause"); But antlr did not accept like as above.
In java class where I am calling the generated java class by Antlr. I am handling like as follows.
try
{
parser.numberRangeCheck();
}
catch (RecognitionException e)
{
throw createException("Invalid Business logic syntax at " + parser.getErrorHeader(e) + ", " + parser.getErrorMessage(e, null), Level.INFO, logger);
}
Any help will be appriciated.
Why not simply throw a RuntimeException with your custom error message?
// ...
else throw new RuntimeException("from value should be less than to value in BETWEEN clause");
// ...
As Terrance wrote in "The Definitive ANTLR Reference" error chapter excerpt:
To avoid forcing English-only error messages and to generally make
things as flexible as possible, the recognizer does not create exception
objects with string messages. Instead, it tracks the information necessary to generate an error.
So there is no error message supplied to RecognitionError's constructor. But you can define additional field of your recognizer to hold user-friendly error message shown on RecognitionError handling:
numberrange returns [String value]
: numberrangesub
{
String numberRange = ($numberrangesub.text);
String [] v = numberRange.split(",");
if ( Integer.parseInt(v[0].trim()) < Integer.parseInt(v[1].trim()))
$value = numberRange;
else {
this.errorMessage = "from value should be less than to value in BETWEEN clause";
throw new RecognitionException(this.input);
}
}
;
And then override the getErrorMessage method:
public String getErrorMessage(RecognitionException e, String[] tokenNames) {
String msg = this.errorMessage;
// ...
}
This works similar to paraphrase mechanism explained in the same excerpt.