Test class not covering method fully? - unit-testing

Hi i have a custom controller which clones opportunity with a new currency,clones quote and all its quote line item.A button on Quote page layout does all this.While writing a test class to cover this code,i could not cover certain lines and do not know why.The code is as follows :
CloneOppNewCurrencyController.cls :
public with sharing class CloneOppNewCurrencyController {
public List<DatedConversionRate>lstCurrencies{get;set;}
public String selectedCurrency{get;set;}
public List<SelectOption> cTypes{get;set;}
public boolean flag{get;set;}
public Date closeDate;
public String qId{get;set;}
public Quote qObj{get;set;}
public Quote qClone{get;set;}
public Opportunity oppObj;
public Opportunity oppClone{get;set;}
public List<QuoteLineItem> lstQuoteLineItems;
public List<QuoteLineItem> lstClonedQuoteLineItems;
public QuoteLineItem clonedQuoteLineItem;
public Double exchangeRate;
public Map<String,Double>mapExchangeRates;
public List<PriceBookEntry> pbe;
public List<Id>pb;
public Quote testClone{get;set;}
public Map<Id,PricebookEntry>mapProIdNpBookEntry;
public List<Renewed_Entitlement__c> lstRE;
public List<Quoted_Asset__c> lstQuotedAsset;
public Renewed_Entitlement__c cloneRE;
public Quoted_Asset__c cloneQA;
//Constructor
public CloneOppNewCurrencyController() {
pb = new List<Id>();
lstRE = new List<Renewed_Entitlement__c>();
lstQuotedAsset = new List<Quoted_Asset__c>();
lstclonedQuoteLineItems = new List<QuoteLineItem>();
mapProIdNpBookEntry = new Map<Id,PriceBookEntry>();
//get quote Id from Page
qId=Apexpages.currentPage().getParameters().get('id');
//Get the Opp Id
qObj=[Select q.Total_Price__c, q.Total_Margin__c, q.Total_Cost__c, q.TotalPrice, q.Tax, q.SystemModstamp, q.Subtotal,
q.Status, q.Siebel_Id__c, q.ShippingStreet, q.ShippingState, q.ShippingPostalCode, q.ShippingName, q.ShippingHandling,
q.ShippingCountry, q.ShippingCity, q.Revision_Number__c, q.Quote_Expiry__c, q.Quote_Date__c, q.QuoteToStreet,
q.QuoteToState, q.QuoteToPostalCode, q.QuoteToName, q.QuoteToCountry, q.QuoteToCity, q.QuoteNumber, q.Pricebook2Id,
q.Price_Book__c, q.Phone, q.Opportunity.Id, q.OpportunityId, q.Name, q.LineItemCount, q.LastModifiedDate,
q.LastModifiedById, q.IsSyncing, q.IsDeleted, q.Internal_Notes__c, q.Id, q.GrandTotal, q.Fax, q.Email, q.Discount,
q.Description, q.Default_Payment_Terms__c, q.Customer_Comments__c, q.CurrencyIsoCode, q.CreatedDate, q.CreatedById,
q.ContactId, q.BillingStreet, q.BillingState, q.BillingPostalCode, q.BillingName, q.BillingCountry, q.BillingCity, q.Opportunity.CloseDate,
q.AdditionalStreet, q.AdditionalState, q.AdditionalPostalCode, q.AdditionalName, q.AdditionalCountry, q.AdditionalCity,
q.Account_Number__c, q.Account_Manager__c, q.Account_Manager_Phone__c, q.Account_Manager_Fax__c, q.Account_Manager_Email__c ,
q.Pricebook2.Organisation__c, q.Pricebook2.External_Id__c, q.Pricebook2.IsStandard, q.Pricebook2.Description, q.Pricebook2.IsActive,
q.Pricebook2.CurrencyIsoCode, q.Pricebook2.Name
From Quote q
where q.Id =:qId];
closeDate = qObj.Opportunity.CloseDate;
cTypes=new List<SelectOption>();
mapExchangeRates = new Map<String,Double>();
cTypes.add(new SelectOption('None','None'));
for(DatedConversionRate d:[Select StartDate, NextStartDate, IsoCode, Id, ConversionRate From DatedConversionRate where StartDate<=:closeDate and NextStartDate >=:closeDate]){
cTypes.add(new SelectOption(d.IsoCode,d.IsoCode));
mapExchangeRates.put(d.IsoCode,d.ConversionRate);
}
//query all fields in Opp which has this quote to clone it
oppObj = [Select o.X18_Character_Id__c, o.Win_Loss_Reason_Details__c, o.Win_Loss_Cancelled_Reason__c, o.Where_is_A_End__c,
o.Upload_Date_Time__c, o.Type, o.Total_Price__c, o.Total_Margin_in_Account_Currency__c, o.Total_Margin__c,
o.Total_Cost__c, o.Timescale__c, o.Technology_Margin__c, o.SystemModstamp, o.SyncedQuoteId, o.Suspended__c,
o.Start_of_Close_Date_FY__c, o.Start_of_Close_Date_FY_2__c, o.Start_of_Close_Date_FY_1__c, o.StageName,
o.Solution_Type__c, o.Solution_Description__c, o.Signed_SOW_Received__c, o.Siebel_Id__c, o.Service_Start_Date__c,
o.SecureCall_Margin__c, o.Salesforce_Opportunity_Id__c, o.Risk_Level__c, o.Regional_Contact_for_SFOne__c,
o.RecordTypeId, o.RFSDate__c, o.Probability, o.Primary_Competitor__c, o.Pricebook2Id, o.PS_Margin__c,
o.PO_Number__c, o.Owner_Affiliates__c, o.OwnerId, o.Other_Margin__c, o.Organisation__c,
o.OpenAir_Project_Reference__c, o.Number_of_Line_items__c, o.Non_Portfolio__c, o.NextStep, o.Need__c,
o.Name, o.NTT_Service_Family_Name__c, o.Maintenance_Margin__c, o.MSS_Margin__c, o.Lost_to__c, o.LeadSource,
o.Last_Update_Date_of_Phase__c, o.LastModifiedDate, o.LastModifiedById, o.LastActivityDate, o.Large_Deal__c,
o.IsWon, o.IsDeleted, o.IsClosed, o.Id, o.HasOpportunityLineItem, o.Group_Collaborator_s_Name__c,
o.ForecastCategoryName, o.ForecastCategory, o.FiscalYear, o.FiscalQuarter, o.Fiscal, o.ExpectedRevenue,
o.End_Customer__c, o.Description, o.CurrencyIsoCode, o.CreatedDate, o.CreatedById, o.Contract_Term__c,
o.Collaborate_with__c, o.Closed_Won_Status__c, o.Close_Date_this_FY__c, o.Close_Date_Last_FY__c, o.Pricebook2.CurrencyIsoCode,
o.CloseDate, o.CampaignId, o.Budget__c, o.Authority__c, o.Approval_Status__c, o.Amount, o.Account_Owner_Id__c, o.Pricebook2.IsActive,
o.Pricebook2.Organisation__c, o.Pricebook2.External_Id__c, o.Pricebook2.IsStandard, o.Pricebook2.Description, o.Pricebook2.Name ,
o.Account_Currency__c, o.AccountId, o.A_End_or_B_End_or_C_End__c
From Opportunity o
where o.Id =: qObj.OpportunityId];
lstQuoteLineItems = [Select q.Vendor_Cost_Name__c, q.UnitPrice, q.Total_Price__c, q.Total_Exchanged_Cost__c, q.Takeover_PPP__c, q.SystemModstamp,
q.Subtotal_Price__c, q.Subtotal, q.SortOrder, q.Single_Creation__c, q.Siebel_Id__c, q.Service_Start_Date__c,
q.Service_End_Date__c, q.Service_Calendar_Business_Hours__c, q.ServiceDate, q.Requested_Ship_Date__c, q.Renewed_Entitlement__c,
q.Renewal_Product__c, q.QuoteId, q.Quantity, q.PricebookEntryId, q.Price__c, q.Organisation__c, q.ListPrice, q.Line_No__c,
q.LineNumber, q.LastModifiedDate, q.LastModifiedById, q.IsDeleted, q.Install_Post_Code__c, q.Install_County_State__c,
q.Install_Country__c, q.Install_Contact__c, q.Install_City__c, q.Id, q.Exchanged_Cost__c, q.Exchange_Rate__c,
q.Discount__c, q.Discount, q.Description, q.Customer_Note__c, q.CurrencyIsoCode, q.CreatedDate, q.CreatedById,
q.Covered_Product__c, q.Covered_Asset__c, q.Cost__c, q.Cost_Price_Original__c, q.Cost_Exchange_Date__c,
q.Cost_Currency__c, q.Consolidated_Entitlement__c, q.Comments__c, q.Asset_Expires__c, q.Address_2__c, q.Vendor_RRP__c,
q.PricebookEntry.IsDeleted, q.PricebookEntry.ProductCode, q.PricebookEntry.SystemModstamp, q.PricebookEntry.LastModifiedById,
q.PricebookEntry.LastModifiedDate, q.PricebookEntry.CreatedById, q.PricebookEntry.CreatedDate, q.PricebookEntry.UseStandardPrice,
q.PricebookEntry.IsActive, q.PricebookEntry.UnitPrice, q.PricebookEntry.CurrencyIsoCode, q.PricebookEntry.Product2Id,
q.PricebookEntry.Pricebook2Id, q.PricebookEntry.Name, q.PricebookEntry.Id,
q.Address_1__c From QuoteLineItem q
where q.QuoteId =:qObj.Id];
for(QuoteLineItem oLineItem : lstQuoteLineItems) {
pb.add(oLineItem.PricebookEntry.Product2Id);
}
//query renewal entitlements under the query to clone it
lstRE = [Select r.Quote__c, r.Quote_Status__c, r.Quote_Line_Item__c, r.Opportunity__c, r.Name, r.Id, r.Entitlement__c,
r.Entitlement_Start_Date__c, r.Entitlement_Service_Calendar__c, r.Entitlement_Part_Code__c, r.Entitlement_End_Date__c,
r.CurrencyIsoCode
From Renewed_Entitlement__c r
where r.Quote__c =:qId ];
//query quoted assets under the query to clone it
lstQuotedAsset = [Select q.Quote__c, q.Name, q.Id, q.CurrencyIsoCode, q.Asset__c
From Quoted_Asset__c q
where q.Quote__c =:qId];
}
public void proceed() {
try {
if(selectedCurrency == 'None' || selectedCurrency == '') {
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Please select a currency in order to proceed'));
}
pbe = [Select p.UnitPrice, p.Product2Id, p.Pricebook2Id, p.Name, p.IsActive, p.Id, p.CurrencyIsoCode From PricebookEntry p
where p.CurrencyIsoCode =:selectedCurrency and p.Pricebook2Id =:oppObj.Pricebook2Id and p.Product2Id in :pb];
for(PricebookEntry pbe : pbe) {
mapProIdNpBookEntry.put(pbe.Product2Id,pbe);
}
for(QuoteLineItem oLine:lstQuoteLineItems) {
if(!mapProIdNpBookEntry.containsKey(oLine.PricebookEntry.Product2Id)) {
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'No pricebook entry exists for this particular currency.Hence kindly create an entry with the selected currency before cloning Opportunity.'));
return;
}
}
if(selectedCurrency!='None') {
if(oppObj.StageName!='Qualification') {
oppClone = oppObj.clone(false,true);
oppClone.ForecastCategoryName = 'Omitted';
oppClone.CurrencyIsoCode = selectedCurrency;
System.debug('Pricebook2Id::::' +oppClone.Pricebook2Id);
oppClone.Pricebook2Id = oppObj.Pricebook2Id;
oppClone.Name = selectedCurrency + oppObj.Name;
Database.insert(oppClone);
System.debug('Inserted Opp Currency >>> ' + oppClone.CurrencyIsoCode);
if(qObj.IsSyncing != true) {
qClone = qObj.clone();
qClone.Name = selectedCurrency + qObj.Name;
qClone.OpportunityId = oppClone.Id;
Database.insert(qClone);
System.debug('Inserted Quote Currency >>> ' + qClone.CurrencyIsoCode);
testClone= [SELECT Id, CurrencyIsoCode FROM Quote WHERE ID=:qClone.Id];
oppClone.SyncedQuoteId = qClone.Id;
}
else {
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Synced Quote cannot be cloned.Please stop sync before cloning'));
}
Database.update(oppClone);
System.debug('Inserted Quote Currency >>> ' + testClone.CurrencyIsoCode);
}
if((lstRE!=null || !(lstRE.isEmpty())) && qClone.Id !=null) {
for(Renewed_Entitlement__c re:lstRE) {
cloneRE = new Renewed_Entitlement__c();
cloneRE = re.clone();
cloneRE.Quote__c = qClone.Id;
Database.insert(cloneRE);
}
}
if((lstQuotedAsset!=null || !(lstQuotedAsset.isEmpty())) && qClone.Id !=null) {
for(Quoted_Asset__c qa:lstQuotedAsset) {
cloneQA = new Quoted_Asset__c();
cloneQA = qa.clone();
cloneQA.Quote__c = qClone.Id;
Database.insert(cloneQA);
}
}
System.debug('^^^aaa^^^^^^^^'+mapProIdNpBookEntry);
if(qClone!=null) {
if(lstQuoteLineItems!=null) { System.debug('not null line items');//tbd
for(QuoteLineItem oLine:lstQuoteLineItems) {
clonedQuoteLineItem = new QuoteLineItem();
clonedQuoteLineItem = oLine.clone();
system.debug('^^12111111' + oLine.PricebookEntry.Product2Id);
if(mapProIdNpBookEntry.containsKey(oLine.PricebookEntry.Product2Id)) {
clonedQuoteLineItem.PricebookEntryId=mapProIdNpBookEntry.get(oLine.PricebookEntry.Product2Id).Id;
}
clonedQuoteLineItem.QuoteId = qClone.Id;
System.debug('Quote line Iso Code'+clonedQuoteLineItem.CurrencyIsoCode);
//update price,margin and vendors
if(mapExchangeRates.containsKey(selectedCurrency)) { System.debug('$$$containsKey iruku$$$'+'###value is###'+mapExchangeRates.get(selectedCurrency));
if(oLine.Price__c!=null && mapExchangeRates.get(selectedCurrency)!=0) {
clonedQuoteLineItem.Price__c = oLine.Price__c / mapExchangeRates.get(clonedQuoteLineItem.CurrencyIsoCode);
}
if(oLine.UnitPrice != null && mapExchangeRates.get(selectedCurrency)!=0) {
clonedQuoteLineItem.UnitPrice = oLine.UnitPrice / mapExchangeRates.get(clonedQuoteLineItem.CurrencyIsoCode);
}
if(oLine.Vendor_RRP__c != null && mapExchangeRates.get(selectedCurrency)!=0) {
clonedQuoteLineItem.Vendor_RRP__c = oLine.Vendor_RRP__c / mapExchangeRates.get(clonedQuoteLineItem.CurrencyIsoCode);
}
}
lstclonedQuoteLineItems.add(clonedQuoteLineItem);
}
System.debug(' >>> ' + lstclonedQuoteLineItems);
if(lstclonedQuoteLineItems.size()>0) {
insert lstclonedQuoteLineItems;
}
}
}
}
}catch(Exception e) {
}
}
public pageReference cancel() {
return null;
}
}
testCloneNewCurrencyController.cls
#isTest(SeeALLData=true)
private class testCloneNewCurrencyController {
static testMethod void myUnitTest() {
// TO DO: implement unit test
Account account=new Account(Name='Test');
insert account;
Contact cn=new Contact(Accountid=account.id);
cn.LastName='test';
insert cn;
// set up opportunity name and price book id
String opportunityName = 'My Opportunity';
String standardPriceBookId = '';
PriceBook2 pb2Standard = [select Id from Pricebook2 where isStandard=true];
standardPriceBookId = pb2Standard.Id;
// set up opp and Verify that the results are as expected.
Opportunity o = new Opportunity(AccountId=account.Id, Name=opportunityName,
StageName='Prospecting', CloseDate=Date.today(),Contract_Term__c = 6);
insert o;
Opportunity opp = [SELECT Name FROM Opportunity WHERE Id = :o.Id];
System.assertEquals(opportunityName, opp.Name);
// set up product2 and Verify that the results are as expected.
Product2 p2 = new Product2(Name='Test Product',isActive=true,Product_Code_Upload__c = 'Test Product 1' , ProductCode = 'Test Product 1');
insert p2;
Product2 p2ex = [SELECT Name FROM Product2 WHERE Id = :p2.Id];
System.assertEquals('Test Product', p2ex.Name);
// set up PricebookEntry and Verify that the results are as expected.
PricebookEntry pbe = new PricebookEntry(Pricebook2Id=standardPriceBookId, Product2Id=p2.Id, UnitPrice=99, isActive=true );
insert pbe;
PricebookEntry pbeex = [SELECT Pricebook2Id FROM PricebookEntry WHERE Id = :pbe.Id];
System.assertEquals(standardPriceBookId, pbeex.Pricebook2Id);
// set up OpportunityLineItem and Verify that the results are as expected.
OpportunityLineItem oli = new OpportunityLineItem(PriceBookEntryId=pbe.Id, OpportunityId=o.Id, Quantity=1, UnitPrice=99 , Cost_Currency__c = 'USD',Cost__c=2000);
insert oli;
OpportunityLineItem oliex = [SELECT PriceBookEntryId FROM OpportunityLineItem WHERE Id = :oli.Id];
oli.Cost_Currency__C = 'GBP';
update oli;
update account;
Quote quot1 = new Quote(Name='Quote1',OpportunityId=o.Id,Pricebook2Id=standardPriceBookId);
insert quot1;
// set up OpportunityLineItem and Verify that the results are as expected.
QuoteLineItem qli = new QuoteLineItem(QuoteId = quot1.Id,PriceBookEntryId=pbe.Id,UnitPrice=1000, Quantity=1, Price__c=3500 , Cost_Currency__c = 'USD',Cost__c=2000);
insert qli;
// Create two Asset records and relate them to the oli through Ordered Asset records
Asset ass1 = new Asset(Name='Asset1',SerialNumber='12345',AccountId=account.Id,ContactId=cn.Id);
insert ass1;
Asset ass2 = new Asset(Name='Asset1',SerialNumber='678910',AccountId=account.Id,ContactId=cn.Id);
insert ass2;
Quoted_Asset__c ordass1 = new Quoted_Asset__c(Asset__c=ass1.Id,Quote_Line_Item__c=qli.Id,Quote__c=quot1.Id);
insert ordass1;
Quoted_Asset__c ordass2 = new Quoted_Asset__c(Asset__c=ass2.Id,Quote_Line_Item__c=qli.Id,Quote__c=quot1.Id);
insert ordass2;
// Check that the Serial numbers field on the QLI is as expected
QuoteLineItem quot1test = [SELECT LineNumber, Serial_Numbers__c FROM QuoteLineItem WHERE Id =: qli.Id];
Test.startTest();
Test.setCurrentPage(new Pagereference('/apex/CloneOppNewCurrency?id='+quot1.Id));
CloneOppNewCurrencyController c = new CloneOppNewCurrencyController();
c.selectedCurrency = 'USD';
system.assertEquals(c.selectedCurrency, 'USD');
//c.qObj = quot1;
c.proceed();
c.selectedCurrency = 'USD';
System.debug('%%%%%'+c.oppClone+'$$$$$'+c.selectedCurrency+'Opp OBj is:'+c.oppObj);
Test.setCurrentPage(new Pagereference('/apex/CloneOppNewCurrency?id='+quot1.Id));
CloneOppNewCurrencyController c1 = new CloneOppNewCurrencyController();
c1.selectedCurrency = 'None';
Pagereference pr = c1.cancel();
Test.stopTest();
}
}
Lines from 127 are not covered.The proceed method is not covered.Can anyone help me please?

What line does 127 correspond to in your example? Is it if(selectedCurrency!='None') { in the proceed() method?
I'd suggest to extend your exception handling. You basically have:
public void proceed() {
try {
// Most of method body here
} catch(Exception e) {
}
}
It is likely that an exception has occured and has been ignored/lost due to the empty Exception handling. Minimally, write the exception out to the log:
} catch(Exception e) {
System.debug(LoggingLevel.Error, 'BANG! ' + e);
}
That may well reveal in the debug log where your test method is failing.

Related

Create multiple DMN using Java Camunda Springboot starter

I would like to create a Java service that would build a Camunda DMN via code. I'm using camunda-springboot-starter dependency and I'm able to generate the DMN DecisionTable and output of one decision is used in another. I'm using InformationRequirement for same but when I write the model to file and open that file in modeler the arrow is not coming for information requirement and after deploying the decision is not able to get that output.
<
public String generateDMN(String name, String title) throws FileNotFoundException {
DmnModelInstance modelInstance = initializeEmptyDmnModel();
Decision decision = modelInstance.newInstance(Decision.class);
decision.setId(title);
decision.setName(name);
modelInstance.getDefinitions().addChildElement(decision);
List<String[]> rules = new ArrayList<>();
try (CSVReader reader = new CSVReader(new FileReader("/Users/rahulnehete/IdeaProjects/java-rules-engine/src/main/resources/file.csv"))) {
rules = reader.readAll();
} catch (Exception e) {
log.error("Error reading CSV file ", e);
}
DecisionTable decisionTable = modelInstance.newInstance(DecisionTable.class);
decisionTable.setId("DecisionTable_"+name+"_"+title);
decisionTable.setHitPolicy(HitPolicy.COLLECT);
decision.addChildElement(decisionTable);
Decision decision2 = modelInstance.newInstance(Decision.class);
decision2.setId(title + "_2");
decision2.setName(name + "_2");
modelInstance.getDefinitions().addChildElement(decision2);
DecisionTable decisionTable2 = modelInstance.newInstance(DecisionTable.class);
decisionTable2.setId("DecisionTable_"+name+"_"+title+"_2");
decisionTable2.setHitPolicy(HitPolicy.COLLECT);
decision2.addChildElement(decisionTable2);
InformationRequirement infoRequirement = modelInstance.newInstance(InformationRequirement.class, "info1");
decision2.getInformationRequirements().add(infoRequirement);
infoRequirement.setRequiredDecision(decision);
String[] header = rules.remove(0);
String[] varTypes = rules.remove(0);
String[] variables = rules.remove(0);
Long numOfInputs = Arrays.stream(header).filter(k -> k.equalsIgnoreCase("input")).count();
Long numOfOutputs = Arrays.stream(header).filter(k -> k.equalsIgnoreCase("output")).count();
for(int i=0; i<numOfInputs; i++) {
Input ip = generateElement(modelInstance, Input.class, "Input_"+i);
InputExpression inputExpression = generateElement(modelInstance, InputExpression.class);
Text text = modelInstance.newInstance(Text.class);
inputExpression.setText(text);
inputExpression.setTypeRef(varTypes[i]);
ip.setLabel("Input " + i);
ip.setCamundaInputVariable(variables[i]);
ip.setInputExpression(inputExpression);
decisionTable.addChildElement(ip);
}
for(int i=numOfInputs.intValue(); i<=numOfOutputs; i++) {
Output op = generateElement(modelInstance, Output.class, "Output_"+i);
op.setLabel("Output " + i);
op.setName(variables[i]);
op.setTypeRef(varTypes[i]);
decisionTable.addChildElement(op);
}
for(int i = 1; i<rules.size(); i++) {
String[] rule = rules.get(i);
Rule dmnRule = createRule(modelInstance, numOfInputs.intValue(), numOfOutputs.intValue(), rule);
decisionTable.addChildElement(dmnRule);
log.info("Rule {} added", i);
}
Input ip = generateElement(modelInstance, Input.class, "Input_A");
InputExpression inputExpression = generateElement(modelInstance, InputExpression.class);
Text text = modelInstance.newInstance(Text.class);
inputExpression.setText(text);
inputExpression.setTypeRef("string");
ip.setLabel("Input A");
ip.setCamundaInputVariable("minPlafond");
ip.setInputExpression(inputExpression);
decisionTable2.addChildElement(ip);
Output op = generateElement(modelInstance, Output.class, "Output_A");
op.setLabel("Output A");
op.setName("FinalOutput");
op.setTypeRef("string");
decisionTable2.addChildElement(op);
// TODO: variable names
String[] rule = new String[] {"-", "$(minPlafond + " + "\"_Success\")"};
Rule dmnRule = createRule(modelInstance, 1, 1, rule);
decisionTable2.addChildElement(dmnRule);
log.info("Rule {} added", "new");
Dmn.validateModel(modelInstance);
try {
FileOutputStream fos = null;
fos = new FileOutputStream(name + "_" + title + ".dmn");
Dmn.writeModelToStream(fos, modelInstance);
fos.close();
} catch (IOException e) {
log.error("Error writing model instance ", e);
return REConstants.FAILED;
}
return "DMN GENERATED";
}
private DmnModelInstance initializeEmptyDmnModel() {
DmnModelInstance dmnModel = Dmn.createEmptyModel();
Definitions definitions = generateNamedElement(dmnModel, Definitions.class, "definitions", "definitions");
definitions.setNamespace(DmnModelConstants.CAMUNDA_NS);
dmnModel.setDefinitions(definitions);
return dmnModel;
}
private <E extends DmnElement> E generateElement(DmnModelInstance modelInstance, Class<E> elementClass, String id) {
E element = modelInstance.newInstance(elementClass);
element.setId(id);
return element;
}
private <E extends NamedElement> E generateNamedElement(DmnModelInstance modelInstance, Class<E> elementClass, String name, String id) {
E element = generateElement(modelInstance, elementClass, id);
element.setName(name);
return element;
}
private <E extends DmnElement> E generateElement(DmnModelInstance modelInstance, Class<E> elementClass) {
String generatedId = elementClass.getSimpleName() + UUID.randomUUID();
return generateElement(modelInstance, elementClass, generatedId);
}
private Rule createRule(DmnModelInstance dmnModelInstance, int numberOfInputs, int numberOfOutputs, String[] ruleInput) {
Rule rule = dmnModelInstance.newInstance(Rule.class);
for(int i=0; i<numberOfOutputs; i++) {
OutputEntry outputEntry = createOutputEntry(dmnModelInstance, ruleInput[numberOfInputs + i]);
rule.getOutputEntries().add(outputEntry);
}
for (int i = 0; i < numberOfInputs; i++) {
InputEntry inputEntry = createInputEntry(dmnModelInstance, ruleInput[i]);
rule.getInputEntries().add(inputEntry);
}
return rule;
}
private InputEntry createInputEntry(DmnModelInstance dmnModelInstance, String expression) {
Text text = dmnModelInstance.newInstance(Text.class);
text.setTextContent(expression);
InputEntry inputEntry = dmnModelInstance.newInstance(InputEntry.class);
inputEntry.setText(text);
return inputEntry;
}
private OutputEntry createOutputEntry(DmnModelInstance dmnModelInstance, String expression) {
Text text = dmnModelInstance.newInstance(Text.class);
text.setTextContent(expression);
OutputEntry outputEntry = dmnModelInstance.newInstance(OutputEntry.class);
outputEntry.setText(text);
return outputEntry;
}
}
You implemented the decisions, decisions table, input and output as well as info requirement correctly on model level (xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/"). (Dmn.writeModelToFile(new File("src/main/resources/my.dmn"), modelInstance); is little more compact than writing the stream yourself.)
When you compare to a model created by the Modeler, you see that it uses additional namespaces such as xmlns:dmndi="https://www.omg.org/spec/DMN/20191111/DMNDI/". This namespaces defines the diagram information separately from the model, e.g:
<dmndi:DMNDI>
<dmndi:DMNDiagram id="DMNDiagram_12sfwjw">
<dmndi:DMNShape id="DMNShape_1m8k4eq" dmnElementRef="Decision1">
<dc:Bounds height="80" width="180" x="150" y="80" />
</dmndi:DMNShape>
<dmndi:DMNShape id="DMNShape_15h0omx" dmnElementRef="Decision2">
<dc:Bounds height="80" width="180" x="240" y="200" />
</dmndi:DMNShape>
<dmndi:DMNEdge id="DMNEdge_15fnvnh" dmnElementRef="InformationRequirement_0a97hay">
<di:waypoint x="330" y="200" />
<di:waypoint x="240" y="180" />
<di:waypoint x="240" y="160" />
</dmndi:DMNEdge>
</dmndi:DMNDiagram>
</dmndi:DMNDI>
Unfortunately, the Camunda API currently offers no way of auto-generating or creating this diagram information.You would have to approach this a level lower with an XML library.
The model is executable without the diagram information. So, you will have a working model. Maybe that is acceptable and only if a human cares about the DRD it can be created manually?
An alternative would be to abandon the Java approach and try https://bpmn.io/toolkit/dmn-js/.

Components and ColdFusion 8

I wrote a cfc to handle all of the functions for one aspect of a project. I typically write in tags but chose to learn something new so I wrote it in script. All my workup and testing was done on a CommandBox running Lucee for quick spin up and a dev environment. It worked like a charm. Now when I uploaded it to our production server running ACF 8 it will not read any of the file. I navigate to the address of the cfc and where it would typically display the functions that are accessible I get the code in a paragraph.
Before I rewrite this in tags I want to make sure that it is a compatibility issue with ACF 8 and not my code and/or any work a rounds. Please do not hammer me for not using params.
Here is my code:
component {
DSN = 'xxxx';
public function init(){
}
remote function BranchContact(MainContactID, BranchOfContactID, UserID) returnformat="plain"{
data = IsBranch(BranchOfContactID);
if(data.branchTotal == 0){
// result = 'no branches';
result = InsertBranch(MainContactID, BranchOfContactID, UserID);
//WriteBranchingHistory(MainContactID, BranchOfContactID, UserID);
result = 1;
}
else{
// message = 'It appears that you are branching to an account is already a branch - from component';
queryString = 'Select top 1 ParentCID from branches where ChildCID =' & BranchOfContactID;
data = RunQuery(queryString);
result = data.ParentCID;
}
return result;
}
private function IsBranch(BranchOfContactID){
queryString = 'Select count(*) as branchTotal from branches where ChildCID = ' & BranchOfContactID;
RunQuery(queryString);
return data;
}
private function InsertBranch(ParentCID, ChildCID, UserID){
// try{
queryString = 'Insert into Branches (ParentCID, ChildCID, UserID) values (' & ChildCID & ', ' & ParentCID & ', '& UserID & ')';
data = RunQuery(queryString);
//WriteBranchingHistory(MainContactID, BranchOfContactID, UserID);
//need to write the branching history to the contact history table so that is can be tracked
contactResultsID = 102;
note = 'Account branched to - ' & ChildCID;
quotedNote = ''''&note&'''';
activityType = 'Branched';
quotedActivity = ''''&activityType&'''';
campaignID = 0;
today = 'getdate()';
AddContactHistory(ParentCID, today, contactresultsID, UserID, quotedActivity, quotedNote, campaignID);
//return history;
return data;
// }
// catch(e){
// errorMessage = 'While trying to branch account';
// message = error(errorMessage);
// return message;
// }
}
remote function Delete(ChildCID, UserID) returnformat="plain"{
// try{
//have to use a query to get the parentcid since it will be empty when the ajax query is triggered
Parent = GetParent(ChildCID);
queryString = 'Delete from branches where ChildCID = ' & ChildCID;
data = RunQuery(queryString);
//WriteBranchingHistory(MainContactID, BranchOfContactID, UserID)
contactResultsID = 103;
note = 'Account unbranched from - ' & Parent.parentCID;
quotedNote = ''''&note&'''';
activityType = 'Removed Branch';
quotedActivity = ''''&activityType&'''';
campaignID = 0;
today = 'getdate()';
AddContactHistory(ChildCID, today, contactresultsID, UserID, quotedActivity, quotedNote, campaignID);
return data;
// }
// catch(e){
// errorMessage = 'While trying to delete branching';
// message = error(errorMessage);
// return e;
// }
}
private function Update(){
}
<!--- WriteBranchHistory has not been completed
public function WriteBranchingHistory(MainContactID, BranchOfContactID, UserID) returnformat="plain"{
try{
queryString = 'insert into BranchHistory(contactID, ChildContactID, UserID, InsertDate) values
('& MainContactiD &', '& BranchContactID & ', ' & UserID & ', getdate());';
data = RunQuery(queryString);
// return data;
//oldMar = GetOldMar(MainContactID);
// writeDump(oldMar);
// writeDump(queryString);
//return oldMar;
}
catch(e){
errorMessage = 'While trying to add branch history';
message = error(errorMessage);
return message;
}
}
--->
public function GetParent(ChildCID) returnformat="html"{
queryString = 'Select top 1 parentCID from branches where childCID = ' & ChildCID;
data = RunQuery(queryString);
return data;
}
public function GetUserInfo(userid){
myQuery = new Query();
myQuery.addParam(name="userid", value=userid, cfsqltype="cf_sql_numeric");
myQuery.setDataSource(DSN);
myQuery.setSQL('select * from users where userid = :userid');
data = myQuery.execute().getResult();
return data;
}
private function RunQuery(queryString){
myQuery = new Query();
// myQuery.addParam(name="ContactID", value=ContactID, cfsqltype="cf_sql_numeric");
myQuery.setDataSource(DSN);
myQuery.setSQL(queryString);
data = myQuery.execute().getResult();
return data;
}
private function error(errorMessage){
message = "Oops something went wrong <br/>" & errorMessage;
return message;
}
private function AddContactHistory(ParentCID, today, contactresultsID, UserID, quotedActivity, quotedNote, campaignID) {
InsertHistoryString = 'insert into contacthistory (contactid, historydate, contactresultID, userid, activitytype, note, campaignID) values
('&ParentCID& ', ' &today& ', ' &contactresultsID& ', ' &UserID& ', ' &quotedActivity& ', ' &quotedNote& ', ' &CampaignID& ');';
InsertHistory = RunQuery(InsertHistoryString);
}
}
component was not supported in cfscript until CF9, so yes, this is a compatibility issue.
Pete Freitag on his blog has a good cheatsheet for cfscript compatability, linked here: https://www.petefreitag.com/cheatsheets/coldfusion/cfscript/

pig puzzle: re-writing an involved reducer as a simple pig script?

There are account ids, each with a timestamp grouped by username. foreach of these username groups I want all pairs of (oldest account, other account).
I have a java reducer that does that, can I rewrite it as a simple pig script?
Schema:
{group:(username),A: {(id , create_dt)}
Input:
(batman,{(id1,100), (id2,200), (id3,50)})
(lulu ,{(id7,100), (id9,50)})
Desired output:
(batman,{(id3,id1), (id3,id2)})
(lulu ,{(id9,id7)})
Not that anyone seems to care, but here goes. You have to create a UDF:
desired = foreach my_input generate group as n, FIND_PAIRS(A) as pairs_bag;
And the UDF:
public class FindPairs extends EvalFunc<DataBag> {
#Override
public DataBag exec(Tuple input) throws IOException {
Long pivotCreatedDate = Long.MAX_VALUE;
Long pivot = null;
DataBag accountsBag = (DataBag) input.get(0);
for (Tuple account : accountsBag){
Long accountId = Long.parseLong(account.get(0).toString());
Long creationDate = Long.parseLong(account.get(4).toString());
if (creationDate < pivotCreatedDate ) {
// pivot is the one with the minimal creation_dt
pivot = accountId;
pivotCreatedDate = creationDate;
}
}
DataBag allPairs = BagFactory.getInstance().newDefaultBag();
if (pivot != null){
for (Tuple account : accountsBag){
Long accountId = Long.parseLong(account.get(0).toString());
Long creationDate = Long.parseLong(account.get(4).toString());
if (!accountId.equals(pivot)) {
// we don't want any self-pairs
Tuple output = TupleFactory.getInstance().newTuple(2);
if (pivot < accountId){
output.set(0, pivot.toString());
output.set(1, accountId.toString());
}
else {
output.set(0, accountId.toString());
output.set(1, pivot.toString());
}
allPairs.add(output);
}
}
return allPairs;
}
and if you wanna play real nicely, add this:
/**
* Letting pig know that we emit a bag with tuples, each representing a pair of accounts
*/
#Override
public Schema outputSchema(Schema input) {
try{
Schema pairSchema = new Schema();
pairSchema.add(new FieldSchema(null, DataType.BYTEARRAY));
pairSchema.add(new FieldSchema(null, DataType.BYTEARRAY));
return new Schema(
new FieldSchema(null,
new Schema(pairSchema), DataType.BAG));
}catch (Exception e){
return null;
}
}
}

how to generate fake data using moq for unit test?

I need to generate some data to unit test my repositories. i was using a loop to generate a list of objects, see codes below. I learned moq is a great mocking library, Can I use moq to generate that and how do I do it?
public IQueryable<Category> GetCategories()
{
IList<Category> result = new List<Category>();
for (int i = 1; i <= 2; i++)
{
Category c = new Category();
c.ID = i;
c.Name = "Parent" + i.ToString();
c.ParentID = 0;
for (int x = i*10; x < i*10+5; x++)
{
Category sub = new Category();
sub.ID = x;
sub.Name = "Sub" + x.ToString();
sub.ParentID = i;
result.Add(sub);
}
result.Add(c);
}
return result.AsQueryable<Category>();
}
You can't use Moq to create the data, but you can use AutoFixture:
public IQueryable<Category> GetCategories()
{
return fixture.CreateMany<Category>().AsQueryable();
}
However, this will not give you a hierarchical tree. It will return objects like this:
Object 1:
- ID = 0
- ParentID = 1
Object 2:
- ID = 2
- ParentID = 3
etc.
If you really need to have this hierarchical data, you would need to use the following code:
public IQueryable<Category> GetCategories()
{
var result = new List<Category>();
// Create the parents
var parents = fixture.Build<Category>()
.Without(x => x.ParentID)
.CreateMany());
result.AddRange(parents);
result.AddRange(parents.SelectMany(p => fixture.Build<Category>()
.With(x => x.ParentID, p.ID)
.CreateMany()));
return result.AsQueryable();
}
This will add multiple parents with multiple subs for each parent.
You can use faker.net to generate fake data. for Example: for dotnet core project its Faker.NETCore.
dotnet add package Faker.NETCore -v 1.0.1
and then use the same in your code in the following manner:-
public void GetStudent()
{
var st = new Student()
st.FirstName = Faker.Name.First();
st.LastName = Faker.Name.Last();
st.Mobile = Faker.Phone.Number();
}

subsonic 3.0 active record update

I am able to retrieve database values and insert database values, but I can't figure out what the Update() syntax should be with a where statement.
Environment -> ASP.Net, C#
Settings.ttinclude
const string Namespace = "subsonic_db.Data";
const string ConnectionStringName = "subsonic_dbConnectionString";
//This is the name of your database and is used in naming
//the repository. By default we set it to the connection string name
const string DatabaseName = "subsonic_db";
Retreive example
var product = equipment.SingleOrDefault(x => x.id == 1);
Insert Example
equipment my_equipment = new equipment();
try
{
// insert
my_equipment.parent_id = 0;
my_equipment.primary_id = 0;
my_equipment.product_code = product_code.Text;
my_equipment.product_description = product_description.Text;
my_equipment.product_type_id = Convert.ToInt32(product_type_id.SelectedItem.Value);
my_equipment.created_date = DateTime.Now;
my_equipment.serial_number = serial_number.Text;
my_equipment.Save();
}
catch (Exception err)
{
lblError.Text = err.Message;
}
Edit: Think that I was just too tired last night, it is pretty easy to update. Just use the retrieve function and use the Update() on that.
var equip = Equipment.SingleOrDefault(x => x.id == 1);
lblGeneral.Text = equip.product_description;
equip.product_description = "Test";
equip.Update();
Resolved. View answer above.