Creating Custom attribute - acumatica

I have to show the price in a mask based on the alphabets setup in the configuration screen.
I am trying to write a custom attribute for the DAC field so that I can use the same in reports.
I have given the existing piece of code below. The function calls are working fine and i am using it for getting value, but I am not able to use it as DAC Attribute
#region PXPriceMaskAttribute
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Class)]
public class PXPriceMaskAttribute : PXStringAttribute
{
#region Ctor
public PXPriceMaskAttribute()
: base()
{
}
#endregion
#region Implementation
/// <exclude/>
///
public static string GetPriceMask(PXGraph grp , decimal? val)
{
string _maskedstring = string.Empty;
decimal value = val ?? 0m;
int ivalue = Convert.ToInt32(Math.Floor(value));
if (ivalue > 0)
{
MemoSetUp setUp = PXSelect<MemoSetUp>.Select(grp);
char[] arr = ivalue.ToString().ToCharArray();
char prevvalue = ' ';
foreach (char cval in arr)
{
if (prevvalue != cval)
{
prevvalue = cval;
switch (cval)
{
case '1': _maskedstring += setUp.N1; break;
case '2': _maskedstring += setUp.N2; break;
case '3': _maskedstring += setUp.N3; break;
case '4': _maskedstring += setUp.N4; break;
case '5': _maskedstring += setUp.N5; break;
case '6': _maskedstring += setUp.N6; break;
case '7': _maskedstring += setUp.N7; break;
case '8': _maskedstring += setUp.N8; break;
case '9': _maskedstring += setUp.N9; break;
case '0': _maskedstring += setUp.N0; break;
default: break;
}
}
else
{
_maskedstring += setUp.Repeate;
}
}
}
return _maskedstring;
}
public static string GetPriceMask(MemoSetUp setUp, decimal? val)
{
string _maskedstring = string.Empty;
decimal value = val ?? 0m;
int ivalue = Convert.ToInt32(Math.Floor(value));
if (ivalue > 0)
{
char[] arr = ivalue.ToString().ToCharArray();
char prevvalue = ' ';
foreach (char cval in arr)
{
if (prevvalue != cval)
{
prevvalue = cval;
switch (cval)
{
case '1': _maskedstring += setUp.N1; break;
case '2': _maskedstring += setUp.N2; break;
case '3': _maskedstring += setUp.N3; break;
case '4': _maskedstring += setUp.N4; break;
case '5': _maskedstring += setUp.N5; break;
case '6': _maskedstring += setUp.N6; break;
case '7': _maskedstring += setUp.N7; break;
case '8': _maskedstring += setUp.N8; break;
case '9': _maskedstring += setUp.N9; break;
case '0': _maskedstring += setUp.N0; break;
default: break;
}
}
else
{
_maskedstring += setUp.Repeate;
}
}
}
return _maskedstring;
}
public override void FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e)
{
if (e.NewValue != null && !e.Cancel)
{
decimal? value = Convert.ToDecimal(e.NewValue);
e.NewValue = GetPriceMask(sender.Graph, value);
}
}
/// <exclude/>
public override void FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
{
if (_AttributeLevel == PXAttributeLevel.Item || e.IsAltered)
{
e.ReturnState = PXStringState.CreateInstance(e.ReturnState, _Length, _IsUnicode, _FieldName, _IsKey, null, _InputMask, null, null, null, null);
}
}
/// <exclude/>
#endregion
}
#endregion
The above piece of code is not working. What is the best way to fix the issue.
Update
I have created a BQL Evaluator and attached to DAC and it always returns zero.
public class PriceRounding<PriceField> : BqlFormulaEvaluator<PriceField>, IBqlOperand
where PriceField : IBqlField
{
public override object Evaluate(PXCache cache, object item,
Dictionary<Type, object> pars)
{
PXFieldState fState = cache.GetStateExt<PriceField>(item) as PXFieldState;
return GetSortOrderValueExt(Convert.ToDecimal(fState.Value));
}
public decimal GetSortOrderValueExt(decimal dVal)
{
dVal = Math.Round(dVal, 0);
decimal divider = (dVal <= 5000) ? 25m : (dVal <= 10000) ? 50m : (dVal <= 100000) ? 100m : 500m;
decimal reminder = dVal % divider;
if (reminder > 0)
{
decimal diff = divider - reminder;
dVal = dVal + diff;
}
return dVal;
}
}
The DAC field
#region RetailPrice
public abstract class retailPrice : PX.Data.IBqlField
{
}
protected decimal? _RetailPrice;
[PXDBDecimal(2)]
[PXUIField(DisplayName = "Retail Price")]
[PXFormula(typeof(PriceRounding<InfoInventoryItemAttributeExtNV.retailPrice>))]
public virtual decimal? RetailPrice
{
get
{
return this._RetailPrice;
}
set
{
this._RetailPrice = value;
}
}
#endregion

Consider using custom BQL Function (derived from BqlFormulaEvaluator) – You can refer out-of-box custom BQL functions available in formula sub-folder of PX.Objects source code. Or you can refer KB article where such custom BQL function HierarchySorting is used.

The following code works fine for me for custom rounding off than using BQL Formula Evaluator
#region PXDBPriceRoundingAttribute
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Class)]
public class PXDBPriceRoundingAttribute : PXDBDecimalAttribute
{
#region Implementation
public static decimal Round(decimal value)
{
value = Math.Round(value, 0);
decimal divider = (value <= 5000) ? 25m : (value <= 10000) ? 50m : (value <= 100000) ? 100m : 500m;
decimal reminder = value % divider;
if (reminder > 0)
{
decimal diff = divider - reminder;
value = value + diff;
}
return value;
}
public override void RowSelecting(PXCache sender, PXRowSelectingEventArgs e)
{
base.RowSelecting(sender, e);
string name = _FieldName;
if (sender.GetValue(e.Row, _FieldOrdinal) == null)
{
sender.SetValue(e.Row, _FieldOrdinal, 0m);
}
else
{
decimal? value = sender.GetValue(e.Row, _FieldOrdinal) as decimal?;
decimal _roundedValue = Round(value ?? 0m);
if ((value ?? 0m) != _roundedValue)
{
sender.SetValue(e.Row, _FieldOrdinal, _roundedValue);
}
}
}
public override void FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e)
{
base.FieldUpdating(sender, e);
decimal? value = sender.GetValue(e.Row, _FieldOrdinal) as decimal?;
decimal _roundedValue = Round(value??0m);
if((value??0m) != _roundedValue)
{
sender.SetValue(e.Row, _FieldOrdinal, _roundedValue);
}
}
public void FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
decimal? value = sender.GetValue(e.Row, _FieldOrdinal) as decimal?;
decimal _roundedValue = Round(value ?? 0m);
if ((value ?? 0m) != _roundedValue)
{
sender.SetValue(e.Row, _FieldOrdinal, _roundedValue);
}
}
public override void RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
{
base.RowPersisting(sender, e);
decimal? value = sender.GetValue(e.Row, _FieldOrdinal) as decimal?;
decimal _roundedValue = Round(value ?? 0m);
if ((value ?? 0m) != _roundedValue)
{
sender.SetValue(e.Row, _FieldOrdinal, _roundedValue);
}
}
#endregion
#region Initialization
public override void CacheAttached(PXCache sender)
{
base.CacheAttached(sender);
_Precision = CommonSetupDecPl.PrcCst;
}
#endregion
}
#endregion
Using In DAC
#region WholeSalesPrice
public abstract class wholeSalesPrice : PX.Data.IBqlField
{
}
protected decimal? _WholeSalesPrice;
[PXDBPriceRoundingAttribute()]
[PXUIField(DisplayName = "Wholesale Price")]
public virtual decimal? WholeSalesPrice
{
get
{
return this._WholeSalesPrice;
}
set
{
this._WholeSalesPrice = value;
}
}
#endregion

Related

Acumatica Pagination Implementation for Processing Screen does not returns all applicable values

I have tried to implement pagination for my custom processing screen but not getting all the required values in the grid.
If I am using below code, where I did not implemented pagination and directly using BQL in the foreach() loop for getting the records, I am getting all the applicable values.
public PXCancel<KNPIPaymentFilter> cancel;
public PXFilter<KNPIPaymentFilter> KNPIFilter;
[PXFilterable]
public PXFilteredProcessing<SOOrder, KNPIPaymentFilter> KNPIProcessOrders;
protected bool _PayMethodChanged = false;
protected bool _PayActionChanged = false;
public virtual void KNPIPaymentFilter_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
{
_PayMethodChanged = !sender.ObjectsEqual<KNPIPaymentFilter.paymentMethodID>(e.Row, e.OldRow);
_PayActionChanged = !sender.ObjectsEqual<KNPIPaymentFilter.payPalInvAction>(e.Row, e.OldRow);
}
public IEnumerable kNPIProcessOrders()
{
if (_PayMethodChanged || _PayActionChanged)
KNPIProcessOrders.Cache.Clear();
KNPIPaymentFilter filter = PXCache<KNPIPaymentFilter>.CreateCopy(KNPIFilter.Current);
if (filter.PayPalInvAction == KNPIConstants.SL)
yield break;
foreach (SOOrder order in PXSelect<SOOrder, Where<SOOrder.orderType, Equal<SOOrderTypeConstants.salesOrder>, And<SOOrder.paymentMethodID, Equal<Required<KNPIPaymentFilter.paymentMethodID>>,
And<SOOrder.status, NotEqual<SOOrderStatus.completed>>>>>.Select(this, this.KNPIFilter.Current.PaymentMethodID))
{
KNPIPayments PayPalPayment = new PXSelect<KNPIPayments, Where<KNPIPayments.acmOrderNbr, Equal<Required<KNPIPayments.acmOrderNbr>>,
And<KNPIPayments.acmOrderType, Equal<Required<KNPIPayments.acmOrderType>>>>, OrderBy<Desc<KNPIPayments.lineNbr>>>
(this).SelectWindowed(0, 1, order.OrderNbr, order.OrderType);
if (filter.PayPalInvAction == KNPIConstants.RE)
{
if (PayPalPayment == null || (PayPalPayment != null && PayPalPayment.PayPalInvoiceStatus == KNPIConstants.CANCELLED))
yield return order;
}
else if (filter.PayPalInvAction == KNPIConstants.CH)
{
if (PayPalPayment != null && PayPalPayment.PayPalInvoiceStatus == KNPIConstants.SENT)
yield return order;
}
}
KNPIProcessOrders.Cache.IsDirty = false;
}
But when I am implementing pagination logic like below, I am not getting any of the record in the grid. I have debugged the code and found out in the list object it is loading only 19 records initially but after that other records are not at all loading in the object.
public PXCancel<KNPIPaymentFilter> cancel;
public PXFilter<KNPIPaymentFilter> KNPIFilter;
[PXFilterable]
public PXFilteredProcessing<SOOrder, KNPIPaymentFilter> KNPIProcessOrders;
protected bool _PayMethodChanged = false;
protected bool _PayActionChanged = false;
public virtual void KNPIPaymentFilter_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
{
_PayMethodChanged = !sender.ObjectsEqual<KNPIPaymentFilter.paymentMethodID>(e.Row, e.OldRow);
_PayActionChanged = !sender.ObjectsEqual<KNPIPaymentFilter.payPalInvAction>(e.Row, e.OldRow);
}
public IEnumerable kNPIProcessOrders()
{
if (_PayMethodChanged || _PayActionChanged)
KNPIProcessOrders.Cache.Clear();
KNPIPaymentFilter filter = PXCache<KNPIPaymentFilter>.CreateCopy(KNPIFilter.Current);
if (filter.PayPalInvAction == KNPIConstants.SL)
yield break;
PXSelectBase<SOOrder> cmd = new PXSelect<SOOrder, Where<SOOrder.orderType, Equal<SOOrderTypeConstants.salesOrder>, And<SOOrder.status, NotEqual<SOOrderStatus.completed>,
And<SOOrder.paymentMethodID, Equal<Optional<KNPIPaymentFilter.paymentMethodID>>>>>>(this);
int startRow = PXView.StartRow;
int totalRows = 0;
List<object> list = cmd.View.Select(new[] { KNPIFilter.Current }, null, PXView.Searches,
PXView.SortColumns, PXView.Descendings, PXView.Filters, ref startRow, PXView.MaximumRows, ref totalRows);
foreach (SOOrder order in list)
{
KNPIPayments PayPalPayment = new PXSelect<KNPIPayments, Where<KNPIPayments.acmOrderNbr, Equal<Required<KNPIPayments.acmOrderNbr>>,
And<KNPIPayments.acmOrderType, Equal<Required<KNPIPayments.acmOrderType>>>>, OrderBy<Desc<KNPIPayments.lineNbr>>>
(this).SelectWindowed(0, 1, order.OrderNbr, order.OrderType);
if (this.KNPIFilter.Current.PayPalInvAction == KNPIConstants.RE)
{
if (PayPalPayment == null || (PayPalPayment != null && PayPalPayment.PayPalInvoiceStatus == KNPIConstants.CANCELLED))
yield return order;
}
else if (this.KNPIFilter.Current.PayPalInvAction == KNPIConstants.CH)
{
if (PayPalPayment != null && PayPalPayment.PayPalInvoiceStatus == KNPIConstants.SENT)
yield return order;
}
}
PXView.StartRow = 0;
KNPIProcessOrders.Cache.IsDirty = false;
}
Can someone please help me out, as what I am doing wrong or what I am missing here.

No such property: getToHour for class: OutagePolicyScript

I 've continously getting error:
2019-05-06 14:37:40,128 [EPI-TaskExecutor-1] ERROR
ScriptExecutionExceptionHandler.handleScriptError(31) - Script with id
[3e2fd082-62f3-46a2-8fca-71b1f9cef028] and label [Outage definition
script] reports an error: : No such property: getToHour for class:
OutagePolicyScript.
Outages.xml file is OK, and is placed together with outage.dtd file in correct location.
import java.util.List;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import com.hp.opr.api.scripting.Event;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.lang3.ArrayUtils;
class OutagePolicyScript
{
Object syncObject = new Object();
final static String fileName = "/opt/HP/BSM/Temp/outages.xml"; // for Windows it will be: "d:/HPBSM/Temp/outages.xml";
final static Log s_log = LogFactory.getLog("com.hp.opr.epi.OutagePolicyScript");
List<OutageDefinition> outageDefinitions = new ArrayList<OutageDefinition>();
Thread loadXMLThread;
final boolean isSuppressEventsOrClose = true;
def init()
{
LoadOutagesFromXML r1 = new LoadOutagesFromXML();
loadXMLThread = new Thread(r1);
loadXMLThread.start();
s_log.debug("init finished");
}
def destroy()
{
s_log.debug("going to stop thread....");
loadXMLThread.interrupt();
}
def process(List<Event> events)
{
synchronized(syncObject) {
try
{
events.each {Event event ->
handleEventSuppressionIfNeeded(event, "EST");
//event.setTitle("Modified by CA/EPI: " + event.getTitle());
// always include following check for each event
if(Thread.interrupted())
throw new InterruptedException()
}
}
catch(InterruptedException e)
{
s_log.error("process of events interrupted", e);
}
}
}
private void handleEventSuppressionIfNeeded(Event event, String timezoneId)
{
// Calculate if event was received during the accepted time window.
Date timeRecieved = event.getTimeReceived();
Calendar cal = Calendar.getInstance();
TimeZone tz = TimeZone.getTimeZone(timezoneId);
if (tz != null)
cal = Calendar.getInstance(tz);
cal.setTime(timeRecieved);
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int dow = cal.get(Calendar.DAY_OF_WEEK);
//event.addCustomAttribute("hour", Integer.toString(hour));
//event.addCustomAttribute("minute", Integer.toString(minute));
//event.addCustomAttribute("day of week", Integer.toString(dow));
// go over all the outage definitions, and compare event attributes to the rule
outageDefinitions.each {OutageDefinition outage ->
if (outage.getIsActive()) {
s_log.debug("Checking active rule: " + outage.getDescription());
// check if the event's day of week is one of the outage definition days. in case the rule cross day, reduce 1 for day of week
if (ArrayUtils.contains(outage.getDays(), dow) || (outage.getCrossDay() && ArrayUtils.contains(outage.getDays(), (dow == 1) ? 7 : dow-1 ))) {
// check if event hour and minute are inside rule's from/to
// convert all configurations to minutes
// if the rule cross a day, then add to "to" 24 hours in order to compare from <= event_time < to
// if the rule cross a day AND event hour < "from" then it means the event is in the next day and need to add 24 hours too
int eventTimeInMin = ((hour < outage.getFromHour() && outage.getCrossDay()) ? hour + 24 : hour) * 60 + minute;
int fromInMin = outage.getFromHour() * 60 + outage.getFromMinute();
int toInMin = (outage.getCrossDay() ? outage.getToHour() + 24 : outage.getToHour) * 60 + outage.getToMinute();
if (eventTimeInMin >= fromInMin && eventTimeInMin < toInMin) {
s_log.debug("event time is within this outage rule, proceed to compare event's attributes");
boolean foundMatch = true;
Set<String> attributeNames = outage.getAttributesList().keySet();
attributeNames.each {String name ->
boolean attMatchResult;
// at the moment, all comparisons are using "EQ"
switch (name) {
case "title" : attMatchResult = compareEventAttributeToOutageRuleForcontains("title", event.getTitle(), outage.getAttributesList().get(name)); break;
case "application" : attMatchResult = compareEventAttributeToOutageRule("application", event.getApplication(), outage.getAttributesList().get(name)); break;
case "object" : attMatchResult = compareEventAttributeToOutageRule("object", event.getObject(), outage.getAttributesList().get(name)); break;
case "category" : attMatchResult = compareEventAttributeToOutageRule("category", event.getCategory(), outage.getAttributesList().get(name)); break;
case "subcategory" : attMatchResult = compareEventAttributeToOutageRule("subcategory", event.getSubCategory(), outage.getAttributesList().get(name)); break;
case "nodeHint" : attMatchResult = compareEventAttributeToOutageRuleForcontains("nodeHint", event.getNodeHints().getHint(), outage.getAttributesList().get(name)); break;
default : s_log.error("attribute name [" + name + "] from outages.xml is not supported");
}
s_log.debug("result for attribute [" + name + "] is: " + attMatchResult);
foundMatch &= attMatchResult;
}
s_log.debug("result after processing all attributes in the rule is: " + foundMatch);
if (foundMatch) {
if (isSuppressEventsOrClose)
event.addCustomAttribute("SuppressDueToOutageRule", outage.getDescription());
else
event.setState(LifecycleState.CLOSED);
}
}
else {
s_log.debug("Current rule doesnt match for the event's time, this rule will be skipped");
}
}
else {
s_log.debug("Current rule doesnt match for the event's day, this rule will be skipped");
}
}
}
}
private boolean compareEventAttributeToOutageRule(String eventAttName, String eventAttValue, Set<String> ruleValues)
{
if (ruleValues.contains(eventAttValue)) {
s_log.debug("found match on attribute [" + eventAttName + "], attribute value=" + eventAttValue);
return true;
}
// else, no match
s_log.debug("no match for attribute " + eventAttName);
return false;
}
private boolean compareEventAttributeToOutageRuleForcontains(String eventAttName, String eventAttValue, Set<String> ruleValues)
{
Iterator<String> itr = ruleValues.iterator();
while (itr.hasNext()) {
if (eventAttValue.indexOf(itr.next()) != -1) { // check if the event attribute contains the rule's value
s_log.debug("found match on attribute [" + eventAttName + "], attribute value=" + eventAttValue);
return true;
}
}
// else, no match
s_log.debug("no match for attribute " + eventAttName);
return false;
}
class LoadOutagesFromXML implements Runnable
{
long lastModifiedTime = -1;
public void run()
{
while (!Thread.interrupted()) {
s_log.debug("in running.... current time: " + new Date());
// lock the sync object
synchronized(syncObject) {
long before = System.currentTimeMillis();
readOutageFile();
long after = System.currentTimeMillis();
s_log.debug("Loading outages definitions from XML took [" + (after - before) + "] ms.");
}
Thread.sleep(60000); // 60 seconds
}
s_log.debug("thread interrupted....");
}
private void readOutageFile()
{
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
File f = new File(fileName);
if (f.lastModified() == lastModifiedTime) {
// the file wasnt changed, no need to reload file
s_log.debug("file LastModifiedTime didn't change, no need to reload configuration");
return;
}
// otherwise, clear previous results and reload XML file
outageDefinitions.clear();
s_log.debug("going to load outage.xml");
Document doc = db.parse(f);
NodeList outages = doc.getElementsByTagName("outage");
for (int i=0 ; i<outages.getLength() ; ++i) {
s_log.debug("handle outage: " + Integer.toString(i));
// going to handle specific outage definition
Element aOutage = (Element)outages.item(i);
Element aTimeWindow = (Element)(aOutage.getElementsByTagName("timeWindow").item(0));
outageDefinitions.add(new OutageDefinition(aOutage.getAttribute("description"),
aOutage.getAttribute("isEnabled"),
aTimeWindow.getElementsByTagName("days").item(0).getTextContent(),
parseIntFromStr(aTimeWindow.getElementsByTagName("from").item(0).getTextContent(), true),
parseIntFromStr(aTimeWindow.getElementsByTagName("from").item(0).getTextContent(), false),
parseIntFromStr(aTimeWindow.getElementsByTagName("to").item(0).getTextContent(), true),
parseIntFromStr(aTimeWindow.getElementsByTagName("to").item(0).getTextContent(), false),
parseAttributesFromXML((Element)aOutage.getElementsByTagName("eventsFilter").item(0))));
}
lastModifiedTime = f.lastModified();
s_log.debug("Going to keep lastModifiedTime as " + lastModifiedTime);
}
catch (Exception e) {
s_log.error("caught exception during parsing of outage.xml", e);
lastModifiedTime = -1;
}
}
private int parseIntFromStr(String str, boolean isHour)
{
String[] array = str.trim().split(":");
if (array.length != 2) {
s_log.debug("Bad time format, expect HH:MM format but recieved: " + str);
return -1;
}
if (isHour)
return Integer.parseInt(array[0]);
else
return Integer.parseInt(array[1]);
}
private Map<String, Set<String>> parseAttributesFromXML(Element eventsFilter)
{
Map<String, Set<String>> result = new HashMap<String, Set<String>>();
NodeList eventAttributes = eventsFilter.getElementsByTagName("eventAttribute");
for (int i=0 ; i<eventAttributes.getLength() ; ++i) {
NodeList attributeValues = eventAttributes.item(i).getElementsByTagName("value");
Set<String> values = new HashSet<String>(attributeValues.getLength());
for (int j=0 ; j<attributeValues.getLength() ; j++) {
values.add(attributeValues.item(j).getTextContent());
}
result.put(eventAttributes.item(i).getAttribute("name"), values);
}
return result;
}
}
class OutageDefinition
{
String description;
boolean isActive;
int[] days;
int fromHour;
int fromMinute;
int toHour;
int toMinute;
boolean crossDay;
Map<String, Set<String>> attributesList;
public OutageDefinition(String desc, String active, String outageDays, int oFromHour, int oFromMinute, int oToHour, int oToMinute, Map<String, Set<String>> oAttributes) {
this.description = desc;
this.isActive = Boolean.parseBoolean(active);
this.fromHour = oFromHour;
this.fromMinute = oFromMinute;
this.toHour = oToHour;
this.toMinute = oToMinute;
this.attributesList = oAttributes;
this.crossDay = false;
// check if time cross a day
if (this.fromHour > this.toHour) {
s_log.debug("in rule [" + this.description + "] found time condition that crosses midnight, adjust toHour accordingly");
this.crossDay = true;
}
this.days = getDaysFromString(outageDays);
}
private int[] getDaysFromString(String str)
{
String[] days = str.trim().split(",");
int[] result = new int[days.length];
for (int i=0 ; i<days.length ; ++i) {
switch (days[i]) {
case "Sunday" : result[i] = 1; break;
case "Monday" : result[i] = 2; break;
case "Tuesday" : result[i] = 3; break;
case "Wednesday" : result[i] = 4; break;
case "Thursday" : result[i] = 5; break;
case "Friday" : result[i] = 6; break;
case "Saturday" : result[i] = 7; break;
default : result[i] = -1; break;
}
}
return result;
}
public String getDescription() {
return description;
}
public boolean getIsActive() {
return isActive;
}
public int[] getDays() {
return days;
}
public int getFromHour() {
return fromHour;
}
public int getFromMinute() {
return fromMinute;
}
public int getToHour() {
return toHour;
}
public int getToMinute() {
return toMinute;
}
public Map<String, Set<String>> getAttributesList() {
return attributesList;
}
public boolean getCrossDay() {
return crossDay;
}
}
}
Look closely at this line. You must either call a method (outage.getToHour()) or access a property (outage.getToHour), but here you do both things. Choose what is correct
int toInMin = (outage.getCrossDay() ? outage.getToHour() + 24 : outage.getToHour) * 60 + outage.getToMinute();

Flashlight with strobe: turn flashlight ON when wheel view value is start from 1 to 10 then thread is not stop on zero value

When the strobe value is increased from 1 to 10 the blinking of flashlight will never stop.neither it stops on zero nor it turns on beside it just get blinking and blinking constantly. here i am adding the code which i have written to do so. if someone knows the solutions please help me.
Thread is not stop thread works until you stop debugger..
cheers!
enter code here
flashButton = findViewById(R.id.flash_button);
mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
mCameraId = mCameraManager.getCameraIdList()[0];
} catch (CameraAccessException e) {
e.printStackTrace();
}
flashButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
if (!isTorchOn) {
turnOnFlashLight();
} else {
turnOffFlashLight();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
scrollValue = findViewById(R.id.value);
mWheel = findViewById(R.id.wheel);
mWheel.setOnScrollListener(new Wheel.OnScrollListener() {
#Override
public void onScrollStarted(Wheel view, float value, int roundValue) {
frequency = Math.abs(roundValue);
}
#Override
public void onScrollFinished(Wheel view, float value, int roundValue) {
scrollValue.setText("" + Math.abs(roundValue));
frequency = strobeFrequency(Math.abs(roundValue));
if(isTorchOn && frequency > 0) {
thread = new Thread(stroboRunner);
thread = null;
strobe(frequency);
}
else if(isTorchOn) {
strobe(0);
// thread.stop();
// thread=null;
}
}
#Override
public void onScroll(Wheel view, float value, int roundValue) {
scrollValue.setText("" + Math.abs(roundValue));
frequency = strobeFrequency(Math.abs(roundValue));
if(isTorchOn && frequency > 0) {
// thread = null;
strobe(frequency);
}
}
});
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void turnOnFlashLight() {
/*
if(frequency > 0){
scrollValue.setText("0.0");
}
*/
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mCameraManager.setTorchMode(mCameraId, true);
} else {
try {
camParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
cam.setParameters(camParams);
cam.startPreview();
} catch (RuntimeException e) {
Toast.makeText(this, "Camera Permission is not granted", Toast.LENGTH_SHORT).show();
}
}
flashButton.setImageResource(R.drawable.power_on);
isTorchOn = true;
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void turnOffFlashLight() {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(thread != null){
stroboRunner.stopRunning = true;
thread = null;
}else {
mCameraManager.setTorchMode(mCameraId, false);
}
} else {
try {
if(thread != null){
stroboRunner.stopRunning = true;
thread = null;
}else {
camParams.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
cam.setParameters(camParams);
cam.stopPreview();
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getBaseContext(), "Exception throws in turning off flashlight.", Toast.LENGTH_SHORT).show();
}
}
flashButton.setImageResource(R.drawable.power_off);
isTorchOn = false;
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private int strobeFrequency(int roundValue) {
int freq = 0;
switch (roundValue) {
case 1:
freq = Math.abs(50);
break;
case 2:
freq = Math.abs(150);
break;
case 3:
freq = Math.abs(300);
break;
case 4:
freq = Math.abs(600);
break;
case 5:
freq = Math.abs(900);
break;
case 6:
freq = Math.abs(1200);
break;
case 7:
freq = Math.abs(1500);
break;
case 8:
freq = Math.abs(1800);
break;
case 9:
freq = Math.abs(2000);
break;
case 10:
freq = Math.abs(2300);
break;
}
return freq;
}
#Override
protected void onResume() {
super.onResume();
try {
cam = Camera.open();
camParams = cam.getParameters();
cam.startPreview();
hasCam = true;
} catch (Exception e) {
// TODO: handle exception
}
compass.start();
}
#Override
protected void onPause() {
super.onPause();
compass.stop();
}
#Override
protected void onStop() {
super.onStop();
Log.d(TAG, "stop compass");
compass.stop();
}
private void strobe(int freq) {
if(thread == null){
stroboRunner = new StroboRunner();
stroboRunner.freq = freq;
thread = new Thread(stroboRunner);
thread.start();
} else if(freq == 0 && thread!=null) {
stroboRunner.stopRunning = true;
thread = null;
// thread.stop();
}
}
private class StroboRunner implements Runnable {
int freq;
boolean stopRunning = false;
#Override
public void run() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
try {
while (!stopRunning) {
mCameraManager.setTorchMode(mCameraId, true);
Thread.sleep(2600 - freq);
System.out.println(""+(2600-freq));
// Toast.makeText(MainActivity.this, ""+(2600-freq), Toast.LENGTH_SHORT).show();
mCameraManager.setTorchMode(mCameraId, false);
Thread.sleep(freq);
}
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
// thread=null;
} else {
Camera.Parameters paramsOn = cam.getParameters();
Camera.Parameters paramsOff = camParams;
paramsOn.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
paramsOff.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
try {
while (!stopRunning) {
cam.setParameters(paramsOn);
cam.startPreview();
Thread.sleep(2600 - freq);
cam.setParameters(paramsOff);
cam.startPreview();
Thread.sleep(freq);
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
}

Bluetooth LE with Android Studio: Write Characteristic with buttons

I am new to Android and Bluetooth and suffering with this problem.
I want to write on a specific characteristic if two buttons are touched.
If I touch the first button a number between 0-9 should be count with +1. With the other button the number should be decrease with -1.
As a fundament i use the BluetootleGatt Example App from Google.
In the DeviceControlActivity i changed the following code:
private final ExpandableListView.OnChildClickListener servicesListClickListner =
new ExpandableListView.OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) {
if (mGattCharacteristics != null) {
final BluetoothGattCharacteristic characteristic =
mGattCharacteristics.get(groupPosition).get(childPosition);
final int charaProp = characteristic.getProperties(); //The properties contain a bit mask of property flags indicating
//the features of this characteristic.
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
// If there is an active notification on a characteristic, clear
// it first so it doesn't update the data field on the user interface.
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(
mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
mBluetoothLeService.readCharacteristic(characteristic);
}
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY ) > 0) {
mNotifyCharacteristic = characteristic;
mBluetoothLeService.setCharacteristicNotification(
characteristic, true);
}
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
characteristic.setWriteType(BluetoothGattCharacteristic.PERMISSION_WRITE);
addListenerOnButton();
}
return true;
}
return false;
}
};
Here is my addListenerOnButton() for the two buttons:
public void addListenerOnButton() {
mArrowUp = (ImageButton) findViewById(R.id.arrow_up);
mArrowUp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
mBluetoothLeService.writeCharacteristicUp();
}
});
mArrowDown = (ImageButton) findViewById(R.id.arrow_down);
mArrowDown.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
mBluetoothLeService.writeCharacteristicDown();
}
});
}
They will call the two writeCharacteristic Methods in the BluetoothLeService-Class. For example i post here only the writeCharacteristicUp()-Method:
public boolean writeCharacteristicUp() {
//check mBluetoothGatt is available
if (mBluetoothGatt == null) {
Log.e(TAG, "lost connection");
return false;
}
BluetoothGattService Service = mBluetoothGatt.getService(UUID_DO_LOGGER_TEST);
if (Service == null) {
Log.e(TAG, "service not found!");
return false;
}
BluetoothGattCharacteristic charac = Service
.getCharacteristic(UUID_TEST_NUMBER);
if (charac == null) {
Log.e(TAG, "char not found!");
return false;
}
byte[] value0 = new byte[1];
value0[0] = (byte) 0; //Constant of 0 for comparison later
byte[] value1 = new byte[1];
value1[0] = (byte) 1; //Constant of 1 for comparison later
byte[] value2 = new byte[1];
value2[0] = (byte) 2; //Constant of 1 for comparison later
byte[] value3 = new byte[1];
value3[0] = (byte) 3; //Constant of 1 for comparison later
byte[] value4 = new byte[1];
value4[0] = (byte) 4; //Constant of 1 for comparison later
byte[] value5 = new byte[1];
value5[0] = (byte) 5; //Constant of 1 for comparison later
byte[] value6 = new byte[1];
value6[0] = (byte) 6; //Constant of 1 for comparison later
byte[] value7 = new byte[1];
value7[0] = (byte) 7; //Constant of 1 for comparison later
byte[] value8 = new byte[1];
value8[0] = (byte) 8; //Constant of 1 for comparison later
byte[] value9 = new byte[1];
value9[0] = (byte) 9; //Constant of 1 for comparison later
byte[] actualvalue = charac.getValue();
if (actualvalue == value0) {
charac.setValue(value1);
}
if (actualvalue == value1) {
charac.setValue(value2);
}
if (actualvalue == value2) {
charac.setValue(value3);
}
if (actualvalue == value3) {
charac.setValue(value4);
}
if (actualvalue == value4) {
charac.setValue(value5);
}
if (actualvalue == value5) {
charac.setValue(value6);
}
if (actualvalue == value6) {
charac.setValue(value7);
}
if (actualvalue == value7) {
charac.setValue(value8);
}
if (actualvalue == value8) {
charac.setValue(value9);
}
if (actualvalue == value9) {
charac.setValue(value0);
}
// charac.setValue(value0);
// byte[] actualvaluenew1 = charac.getValue();
boolean status = mBluetoothGatt.writeCharacteristic(charac);
// byte[] actualvaluenew2 = charac.getValue();
return status;
}
The problem is that the
boolean status = mBluetoothGatt.writeCharacteristic(charac)
does not work, the status will be false. And so the actual value is not displayed on the Screen in the corresponding TextView. Why?
Also i found out that the if-grinds are not working because charac.setValue(value0) is only working outside the if-grinds?
I would suggest you press and hold control key and click to BluetoothGatt#writeCharacteristic(ch) function in your code. Then Android Studio will view BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic characteristic) function:
public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
&& (characteristic.getProperties() &
BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false;
if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false;
BluetoothGattService service = characteristic.getService();
if (service == null) return false;
BluetoothDevice device = service.getDevice();
if (device == null) return false;
synchronized(mDeviceBusy) {
if (mDeviceBusy) return false;
mDeviceBusy = true;
}
try {
mService.writeCharacteristic(mClientIf, device.getAddress(),
service.getType(), service.getInstanceId(),
new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
new ParcelUuid(characteristic.getUuid()),
characteristic.getWriteType(), AUTHENTICATION_NONE,
characteristic.getValue());
} catch (RemoteException e) {
Log.e(TAG,"",e);
mDeviceBusy = false;
return false;
}
return true;
}
Put a breakpoint inside the method and do debugging. Here are the possible reasons why you get false based on the source code:
The remote BLE device does not have Write or Write with No Response access
Either your service is null or the characteristic value you set is null
Your device is already doing another BLE process with the remote device
In my opinion, most probably the 2nd item is the reason.

How to sort search dictionary result based on frequency in j2me

This is my dictionary format:
word Frequency
Gone 60
Goes 10
Go 30
So far the system returns words eg starting with 'g' as go30, goes10, gone60 as a list.
(alphabetically). I want to increase the accuracy of the system so that the search result is based on frequency. Words with high frequencies appear first. kindly help.
Here is the Text midlet class that reads the dictionary line by line.
public class Text extends MIDlet {
// Fields
private static final String[] DEFAULT_KEY_CODES = {
// 1
".,?!'\"1-()#/:_",
// 2
"ABC2",
// 3
"DEF3",
// 4
"GHI4",
// 5
"JKL5",
// 6
"MNO6",
// 7
"PQRS7",
// 8
"TUV8",
// 9
"WXYZ9",
};
//Initializing inner Classes
public ComposeText() {
cmdHandler = new CommandHandler();
lineVector = new Vector();
}
//Calling All InitMethods, setting Theme, Show MainForm
public void startApp() {
Display.init(this);
setTheme();
initCmd();
initMainGui();
mainFrm.show();
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
//Initializing all the Commands
public void initCmd() {
exitCmd = new Command("Exit");
selectCmd = new Command("Ok");
cancelCmd = new Command("Cancel");
predCmd = new Command("Prediction");
sendCmd = new Command("Send");
tfPredArea = new TextField();
//check dictionary
try {
readFile();
} catch (IOException ex) {
ex.printStackTrace();
}
}
//Initiating MainScreen
public void initMainGui() {
mainFrm = new Form("Compose Text");
mainFrm.setLayout(new BorderLayout());
mainFrm.setLayout(new CoordinateLayout(150, 150));
mainFrm.addCommand(exitCmd);
mainFrm.addCommand(predCmd);
mainFrm.addCommand(sendCmd);
mainFrm.addCommandListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if(ae.getSource() == predCmd){
initPredGui();
} else if(ae.getSource() == exitCmd){
destroyApp(true);
notifyDestroyed();
}
}
});
// To : 07xxxxxxxxxx
Dimension d1 = new Dimension(130, 20);
lbTo = new Label("To:");
lbTo.setX(10);
lbTo.setY(10);
tfTo = new TextField();
tfTo.setReplaceMenu(false);
tfTo.setConstraint(TextField.NUMERIC);
tfTo.setInputModeOrder(new String[]{"123"});
tfTo.setMaxSize(13);
tfTo.setX(40);
tfTo.setY(10);
tfTo.setPreferredSize(d1);
//Message : Compose Text
Dimension d2 = new Dimension(135, 135);
lbSms = new Label("Message:");
lbSms.setX(5);
lbSms.setY(40);
tfSms = new TextField();
tfSms.setReplaceMenu(false);
tfSms.setX(40);
tfSms.setY(40);
tfSms.setPreferredSize(d2);
//add stuff
mainFrm.addComponent(lbTo);
mainFrm.addComponent(lbSms);
mainFrm.addComponent(tfTo);
mainFrm.addComponent(tfSms);
}
//Initiating FilterSelection Screen
public void initPredGui() {
predForm = new Form("Prediction on");
predForm.setLayout(new CoordinateLayout(150, 150));
predForm.addCommand(cancelCmd);
predForm.addCommand(selectCmd);
//textfied in prediction form
final Dimension d5 = new Dimension(200, 200);
tfPredArea = new TextField();
tfPredArea.setReplaceMenu(false);
tfPredArea.setX(10);
tfPredArea.setY(10);
tfPredArea.setPreferredSize(d5);
predForm.addComponent(tfPredArea);
final ListModel underlyingModel = new DefaultListModel(lineVector);
// final ListModel underlyingModel = new
DefaultListModel(tree.getAllPrefixMatches(avail));
// this is a list model that can narrow down the underlying model
final SortListModel proxyModel = new SortListModel(underlyingModel);
final List suggestion = new List(proxyModel);
tfPredArea.addDataChangeListener(new DataChangedListener() {
public void dataChanged(int type, int index) {
int len = 0;
int i = 0;
String input = tfPredArea.getText();
len = tfPredArea.getText().length();
//ensure start search character is set for each word
if (!(len == 0)) {
for (i = 0; i < len; i++) {
if (input.charAt(i) == ' ') {
k = i;
}
}
String currentInput = input.substring(k + 1, len);
proxyModel.filter(currentInput);
}
}
});
Dimension d3 = new Dimension(110, 120);
suggestion.setX(80);
suggestion.setY(80);
suggestion.setPreferredSize(d3);
predForm.addComponent(suggestion);
suggestion.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
String string = suggestion.getSelectedItem().toString();
if (tfPredArea.getText().charAt(0) == 0) {
tfPredArea.setText(string);
}
else if (tfPredArea.getText().length() == 0) {
tfPredArea.setText(string);
} else {
tfPredArea.setText(tfPredArea.getText() + string);
}
}
});
predForm.addCommandListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == addCmd) {
newDictionaryFrm.show();
} else {
mainFrm.show();
}
}
});
predForm.show();
}
//Setting Theme for All Forms
public void setTheme() {
try {
Resources r = Resources.open("/theme.res");
UIManager.getInstance().setThemeProps(r.getTheme(
r.getThemeResourceNames()[0]));
} catch (java.io.IOException e) {
System.err.println("Couldn't load the theme");
}
}
//Inner class CommandHandler
public class CommandHandler implements ActionListener {
public void actionPerformed(ActionEvent ae) {
//cancelCommand from predictionForm
if (ae.getSource() == cancelCmd) {
if (edit) {
mainFrm.show();
// clearFields();
} else if (ae.getSource() == selectCmd){
tfPredList.addDataChangeListener(model);
predForm.show();
}
else{}
}
}
}
// method that reads dictionary line by line
public void readFile() throws IOException {
tree = new Trie();
InputStreamReader reader = new InputStreamReader(
getClass().getResourceAsStream("/Maa Corpus.txt-01-ngrams-Alpha.txt"));
String line = null;
// Read a single line from the file. null represents the EOF.
while ((line = readLine(reader)) != null) {
// Append to a vector to be used as a list
lineVector.addElement(line);
}
}
public String readLine(InputStreamReader reader) throws IOException {
// Test whether the end of file has been reached. If so, return null.
int readChar = reader.read();
if (readChar == -1) {
return null;
}
StringBuffer string = new StringBuffer("");
// Read until end of file or new line
while (readChar != -1 && readChar != '\n') {
// Append the read character to the string.
// This is part of the newline character
if (readChar != '\r') {
string.append((char) readChar);
}
// Read the next character
readChar = reader.read();
}
return string.toString();
}
}
}
The SortListModel Class has a filter method that gets prefix from the textfield datachangeLister
class SortListModel implements ListModel, DataChangedListener {
private ListModel underlying;
private Vector filter;
private Vector listeners = new Vector();
public SortListModel(ListModel underlying) {
this.underlying = underlying;
underlying.addDataChangedListener(this);
}
private int getFilterOffset(int index) {
if(filter == null) {
return index;
}
if(filter.size() > index) {
return ((Integer)filter.elementAt(index)).intValue();
}
return -1;
}
private int getUnderlyingOffset(int index) {
if(filter == null) {
return index;
}
return filter.indexOf(new Integer(index));
}
public void filter(String str) {
filter = new Vector();
str = str.toUpperCase();
for(int iter = 0 ; iter < underlying.getSize() ; iter++) {
String element = (String)underlying.getItemAt(iter);
if(element.toUpperCase().startsWith(str)) // suggest only if smthing
{
filter.addElement(new Integer(iter));
}
}
dataChanged(DataChangedListener.CHANGED, -1);
}
public Object getItemAt(int index) {
return underlying.getItemAt(getFilterOffset(index));
}
public int getSize() {
if(filter == null) {
return underlying.getSize();
}
return filter.size();
}
public int getSelectedIndex() {
return Math.max(0, getUnderlyingOffset(underlying.getSelectedIndex()));
}
public void setSelectedIndex(int index) {
underlying.setSelectedIndex(getFilterOffset(index));
}
public void addDataChangedListener(DataChangedListener l) {
listeners.addElement(l);
}
public void removeDataChangedListener(DataChangedListener l) {
listeners.removeElement(l);
}
public void addSelectionListener(SelectionListener l) {
underlying.addSelectionListener(l);
}
public void removeSelectionListener(SelectionListener l) {
underlying.removeSelectionListener(l);
}
public void addItem(Object item) {
underlying.addItem(item);
}
public void removeItem(int index) {
underlying.removeItem(index);
}
public void dataChanged(int type, int index) {
if(index > -1) {
index = getUnderlyingOffset(index);
if(index < 0) {
return;
}
}
for(int iter = 0 ; iter < listeners.size() ; iter++) {
((DataChangedListener)listeners.elementAt(iter)).dataChanged(type, index);
}
}
}

Resources