How to group csv data by specific column name row wise using Java 7 only - hashmap

Format of csv is
Row1:c1,c2,c3,c4,c5
Row2:1,a,b,c,d
Row3:1,n,b,c,l
Row4:2,j,k,c,l
Row5:3,a,i,v,i
Row6:1,a,b,c,d
Row7:1,a,b,u,i
Grouping should be done on basis of column c1,c2,c3, if all these three column values are same then group it as follows:
GROUP1: row2 and row 7 are same and map should be Map(Map(String, String),Map(String, String))
i.e. one key{c1,1},{c2,a},{c3,b} (key value pair again)
with multiple values as
{c4,c},{c5,d} (key value pair )
{c4,u},{c5,i} (key value pair )
GROUP2:Row 3 does not have same value with respect to columns so the map should be
key{c1,1}{c2,n}{c3,b}
value{c4,c}{c5,l}
Row7 should be added to error map as the row is same as row2
Final Map should be Map of(group.Num,Objects)
Column name should be picked from property file as shown below.
public class app3 {
public static void main(String args[]) throws IOException {
File CSV_FILE_PATH = new File("csv.csv");
CsvMapReader mapReader = null;
try {
mapReader = new CsvMapReader(new FileReader(CSV_FILE_PATH), CsvPreference.STANDARD_PREFERENCE);
final String[] header = mapReader.getHeader(true);
final CellProcessor[] processors = getProcessors();
Map<String, Object> customerMap;
Map<Integer,Map<String, Object>> finalMap = new HashMap<Integer,Map<String, Object>>();
while( (customerMap = mapReader.read(header, processors)) != null ) {
finalMap.put(mapReader.getLineNumber(), customerMap);
}
}
}
finally {
if( mapReader != null ) {
mapReader.close();
}
}
}
private static CellProcessor[] getProcessors() throws IOException {
InputStream input = new FileInputStream("fileAttributesconfig.properties");
Properties prop= new Properties();
prop.load(input);
CellProcessor[] processors=new CellProcessor[prop.size()];
for(int i=0; i< prop.size(); i++){
processors[i]=new Optional();
}
return processors;
}
}
The have done multiple trials but group by is supported only by 8, but specifically i need to use java 7.Could someone can help me here? I need more ideas to over come this

Related

WordProcessingDocument not preserving whitespace

I'm writing a C# program using XML and Linq that reads in data from tables stored in a word document and inserts it into an excel spreadsheet. The code I have so far does this, however it does not preserve any new lines (in the word doc the "new line" is done by pressing the enter key). Using the debugger, I can see that the new lines aren't even being read in. For example, if the text I want to copy is:
Something like this
And another line
And maybe even a third line
It gets read in as:
Something like thisAnd another lineAnd maybe even a third line
I can't separate the lines by a character as the words could be anything. This is what I have so far:
internal override Dictionary<string, string> GetContent()
{
Dictionary<string, string> contents = new Dictionary<string, string>();
using (WordprocessingDocument doc = WordprocessingDocument.Open(MainForm.WordFileDialog.FileName, false))
{
List<Table> tables = doc.MainDocumentPart.Document.Descendants<Table>().ToList();
foreach (Table table in tables)
{
TableRow headerRow = table.Elements<TableRow>().ElementAt(0);
TableCell tableSectionTitle;
try
{
tableSectionTitle = headerRow.Elements<TableCell>().ElementAt(0);
}
catch (ArgumentOutOfRangeException)
{
continue;
}
List<TableRow> rows = table.Descendants<TableRow>().ToList();
foreach (TableRow row in rows)
{
TableCell headerCell = row.Elements<TableCell>().ElementAt(0);
if (headerCell.InnerText.ToLower().Contains("first item"))
{
contents.Add("first item", row.Elements<TableCell>().ElementAt(1).InnerText);
}
else if (headerCell.InnerText.ToLower().Contains("second item:"))
{
char[] split = { ':' };
Int32 count = 2;
string str = row.Elements<TableCell>().ElementAt(0).InnerText;
String[] newStr = str.Split(split, count, StringSplitOptions.None);
contents.Add("second item:", newStr[1]);
}
**continues for many more else if statements**
else
{
continue;
}
}
}
return contents;
}
}
I'm new to using XML, so any help would be appreciated!

Printing Duplicate Records from the Data View In Acumatica

I am trying to print all records of a data-view into a file using a for loop in my customization in Acumatica. Unfortunately I am ending up with printing the first record everytime resulting into duplication of records, Unable to track where I am going wrong....Please Assist
Here Goes my Code......
public class MayBankGIROProcess : PXGraph<MayBankGIROProcess>
{
public PXSelect<MayBankGIRO> Document; //This is my Data View
public PXAction<MayBankGiroFilter> createTextFile;
[PXUIField(DisplayName = "Create Text File")]
[PXButton()]
public virtual IEnumerable CreateTextFile(PXAdapter adapter)
{
List<string> myList = new List<string> { };
foreach (MayBankGIRO dacRecord in this.Document.Select()) //this is the loop which is taking the data records.
{
myList.Add(dacRecord.ReordType+ "|"+ dacRecord.CustomerReferenceNumber+ "|"+ dacRecord.ClientBatchID+ "|");
// The above line is printing only the first record of the data view everytime .
}
string filename = "DAWN" + ".txt";
Download(myList, filename);
return adapter.Get();
}
public static void Download(List<string> lines, string name) //method generating file
{
var bytes = default(byte[]);
using (MemoryStream stream = new MemoryStream())
{
StreamWriter sw = new StreamWriter(stream);
foreach (string line in lines)
{
sw.WriteLine(line);
}
stream.Position = 0;
bytes = stream.ToArray();
sw.Close();
};
PX.SM.FileInfo textDoc = new PX.SM.FileInfo(name, null, bytes);
if (textDoc != null)
{
throw new PXRedirectToFileException(textDoc, true);
}
else
{
PXTrace.WriteInformation("Could not generate file");
}
}
}
[Generated Text File with all duplicate Record][1]
[1]: https://i.stack.imgur.com/Kllmk.png
[Original Record from database][2]
[2]: https://i.stack.imgur.com/Rbr9k.png
This usually happens when the report is pulling from a SQL View DAC which doesn't have unique key defined. Add IsKey=True on DAC fields until the SQL view is pulling unique record and the error should go away.

Excel stored in List<Map<String,String>>

I am trying to read an excel sheet and save it in Java Data Structure List> list
Basically I am having a table in the excel sheet
|Name|FirstName|emp_ID|Age|
|aaaa|bbbbbbbbb|111111|40 |
|cccc|fffffffff|222222|25 |
where the keys will be
|Name|FirstName|emp_ID|Age|
my list of map should look as bellow
{Name=aaaa, FirstName=bbbbbbbbb, emp_ID=111111, Age=40}
{Name=cccc, FirstName=fffffffff, emp_ID=222222, Age=25}
but my list is storing the second map two times
{Name=cccc, FirstName=fffffffff, emp_ID=222222, Age=25}
{Name=cccc, FirstName=fffffffff, emp_ID=222222, Age=25}
any idea how to fix the issue please or any better suggestion
Thank You in advance
Here is the code That I wrote
workbook = WorkbookFactory.create(inStream);
workSheet = workbook.getSheetAt(0);
DataFormatter df = new DataFormatter();
Map<String, String> myMap = new LinkedHashMap<>();
List<Map<String, String>> list = new ArrayList<>();
row = workSheet.getRow(0);
ArrayList<String> headersName = new ArrayList<String>();
for (int j = 0; j <= row.getPhysicalNumberOfCells(); j++) {
row.getCell(j);
if ((df.formatCellValue(row.getCell(j)).isEmpty())) {
continue;
} else {
headersName.add(df.formatCellValue(row.getCell(j)));
}
}
System.out.println(headersName);
OUTER: for (Row myrow : workSheet) {
for (int i = 0; i < myrow.getLastCellNum(); i++) {
if (myrow.getRowNum() == 0) {
continue OUTER;
}
String value = df.formatCellValue(myrow.getCell(i));
myMap.put(headersName.get(i), value);
}
list.add(myMap);
}
System.out.println(list.size());
for (Map<String, String> map : list) {
System.out.println(map);
}
the print of my list
{Name=cccc, FirstName=fffffffff, emp_ID=222222, Age=25}
{Name=cccc, FirstName=fffffffff, emp_ID=222222, Age=25}
The issue lies in myMap.put(headersName.get(i), value). In that line, if the key already exists in the map, it overrides it. But later on, list.add(myMap) passes a reference to the same map, not a new version of it. So on the second iteration, when the line overrides the value, it overrides it on the first map already in the list. See below for a basic example of the same issue.
import java.util.*;
public class Example {
public static void main(String []args) {
Map<String, String> myMap = new LinkedHashMap<>();
List<Map<String, String>> list = new ArrayList<>();
myMap.put("abc", "123");
list.add(myMap);
System.out.println(list.get(0));
myMap.put("abc", "234");
System.out.println(myMap);
System.out.println(list.get(0));
}
}
To fix it, look into deep copies so that changing one doesn't change them all.

Batch allocation of stock on SOOrder

I am trying to write a process screen to allocate stock on the sales order in FIFO. The Process screen list all the sales order for a period for allocation.
I have gone through the code LSSOLine and not able to figure out the piece of code where allocation is done. anybody knows how to do it?
Update
I have tried the following code and it is working. Is there any better way to do it?
private static void DoStockAllocation(SOLine row, SOOrderEntry grp)
{
try
{
grp.Document.Current = PXSelect<
SOOrder,
Where<SOOrder.orderType, Equal<Required<SOOrder.orderType>>,
And<SOOrder.orderNbr, Equal<Required<SOOrder.orderNbr>>>>>
.Select(grp, row.OrderType, row.OrderNbr);
if (grp.Document.Current != null && grp.Document.Current.Status == SOOrderStatus.Open)
{
grp.Transactions.Current = row;
PXSelectBase<INLocationStatus> cmd = new PXSelectReadonly2<INLocationStatus,
InnerJoin<INLocation, On<INLocation.locationID, Equal<INLocationStatus.locationID>>,
LeftJoin<INSiteStatus, On<INSiteStatus.inventoryID, Equal<INLocationStatus.inventoryID>,
And<INSiteStatus.subItemID, Equal<INLocationStatus.subItemID>,
And<INSiteStatus.siteID, Equal<INLocationStatus.siteID>>>>>>,
Where<INLocationStatus.inventoryID, Equal<Required<INLocationStatus.inventoryID>>,
And<INLocationStatus.subItemID, Equal<Required<INLocationStatus.subItemID>>,
And<INLocationStatus.siteID, Equal<Required<INLocationStatus.siteID>>,
And<INLocation.salesValid, Equal<boolTrue>,
And<INLocation.inclQtyAvail, Equal<boolTrue>,
And<INLocationStatus.qtyOnHand, Greater<decimal0>>>>>>>>(grp);
foreach (PXResult<INLocationStatus, INLocation, INSiteStatus> ln in cmd.Select(row.InventoryID,row.SubItemID,row.SiteID))
{
INLocationStatus locationStatus = ln;
INSiteStatus siteStatus = ln;
SiteStatus accumsiteavail = new SiteStatus();
PXCache<INSiteStatus>.RestoreCopy(accumsiteavail, siteStatus);
accumsiteavail = (SiteStatus)grp.Caches[typeof(SiteStatus)].Insert(accumsiteavail);
decimal? AvailableQty = 0m;
decimal? SiteAvailableQty = locationStatus.QtyHardAvail;//siteStatus.QtyHardAvail + accumsiteavail.QtyHardAvail;
AvailableQty = SiteAvailableQty;
if (AvailableQty <= 0m)
{
continue;
}
if (row.LocationID == null)
{
row.LocationID = locationStatus.LocationID;
grp.Transactions.Update(row);
}
SOLineSplit split = new SOLineSplit();
if ( grp.splits.Select().Count > 0)
{
split = grp.splits.Select(row.OrderType, row.OrderNbr, row.LineNbr);
}
else
{
split = new SOLineSplit();
split = grp.splits.Insert(split);
split.InventoryID = row.InventoryID;
split.SiteID = row.SiteID;
split.OrderType = row.OrderType;
split.OrderNbr = row.OrderNbr;
split.LineNbr = row.LineNbr;
split.UOM = row.UOM;
split = PXCache<SOLineSplit>.CreateCopy(grp.splits.Update(split));
}
//split.LocationID = locationStatus.LocationID;
split.Qty = (AvailableQty < row.OrderQty) ? AvailableQty : row.OrderQty;
split.IsAllocated = true;
grp.splits.Update(split);
break;
}
grp.Save.Press();
}
}
catch(Exception ex)
{
}
}
You will need to reference the combination of LSSOLine and SOLineSplitPlanID on SOLineSplit.PlanID in your process page. Alternatively you might be able to use an instance of SOOrderEntry to do the updates/mark of allocation.
The following have been copied from the SOOrderEntry graph and are the 2 componenetis from what i can tell that drive the allocation logic. From there you just need to mark the split lines that should be allocated and should be good. Or at least a start. The problem you might have is anything that is looking for current SOOrder. You might have to set the current before marking solines splits as allocated. (assuming i under stand your question correctly)
Manage the allocation records...
public LSSOLine lsselect;
Append the use of SOLineSplitPlanID which drives the INItemPlan records...
[PXMergeAttributes(Method = MergeMethod.Append)]
[SOLineSplitPlanID(typeof(SOOrder.noteID), typeof(SOOrder.hold), typeof(SOOrder.orderDate))]
protected virtual void SOLineSplit_PlanID_CacheAttached(PXCache sender)
{
}

Entity Framework - IQueryable to DataTable

I'm trying to convert an IQueryable object to a DataTable. Here's an example of a query that I would like to convert to a DataTable:
var query = DbContext.SomeObjectSet.Select(x => new { PropertyName1 = x.ColumnName1, PropertyName2 = x.ColumnName2 });
Please note the anonymous object that is created in the Select method and the names of the properties:
new { PropertyName1 = x.ColumnName1, PropertyName2 = x.ColumnName2 }
After Googling this issue, I came across the following code that converts an IQueryable object to a DataTable:
public static DataTable EntityToDatatable(this IQueryable result)
{
ObjectQuery query = (result as ObjectQuery);
ObjectContext context = query.Context;
EntityConnection entityCon = (context.Connection as EntityConnection);
using (SqlConnection sqlCon = new SqlConnection(entityCon.StoreConnection.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand(query.ToTraceString(), sqlCon))
{
foreach (var param in query.Parameters)
{
cmd.Parameters.AddWithValue(param.Name, param.Value);
}
using (SqlDataAdapter dataAdapter = new SqlDataAdapter(cmd))
{
using (DataTable dataTable = new DataTable())
{
dataAdapter.Fill(dataTable);
return dataTable;
}
}
}
}
}
The code above "works" and the SQL statement from the ToTraceString() method is as follows:
SELECT [Extent1].[ColumnName1] AS [ColumnName1], [Extent1].[ColumnName2] AS [ColumnName2] FROM [dbo].[TableName] AS [Extent1]
Problem: The column names of the SQL statement (i.e. columnName1 and columnName2) do not correspond to the names of the properties of the objects (i.e. PropertyName1 and PropertyName2) that would be materialized if a ToList() or AsEnumerable() method was called on the query. This wouldn't be so bad if the SQL statement columns were in the same order as the anonymous object properties...but, this is not always the case. Somewhere (I guess inside of the IQueryable object) there must be a mapping between the SQL statement column names and the resulting anonymous object property names.
Does anyone know how to get at this mapping?
I've managed to find a solution to my problem:
First, you need the following code (from How does Entity Framework manage mapping query result to anonymous type?) which maps the positions of my anonymous object properties to the SQL statement column position:
public static Int32[] GetPropertyPositions(this ObjectQuery query)
{
// get private ObjectQueryState ObjectQuery._state;
// of actual type internal class
// System.Data.Objects.ELinq.ELinqQueryState
Object queryState = GetProperty(query, "QueryState");
AssertNonNullAndOfType(queryState, "System.Data.Objects.ELinq.ELinqQueryState");
// get protected ObjectQueryExecutionPlan ObjectQueryState._cachedPlan;
// of actual type internal sealed class
// System.Data.Objects.Internal.ObjectQueryExecutionPlan
Object plan = GetField(queryState, "_cachedPlan");
AssertNonNullAndOfType(plan, "System.Data.Objects.Internal.ObjectQueryExecutionPlan");
// get internal readonly DbCommandDefinition ObjectQueryExecutionPlan.CommandDefinition;
// of actual type internal sealed class
// System.Data.EntityClient.EntityCommandDefinition
Object commandDefinition = GetField(plan, "CommandDefinition");
AssertNonNullAndOfType(commandDefinition, "System.Data.EntityClient.EntityCommandDefinition");
// get private readonly IColumnMapGenerator EntityCommandDefinition._columnMapGenerator;
// of actual type private sealed class
// System.Data.EntityClient.EntityCommandDefinition.ConstantColumnMapGenerator
Object columnMapGenerator = GetField(commandDefinition, "_columnMapGenerator");
AssertNonNullAndOfType(columnMapGenerator, "System.Data.EntityClient.EntityCommandDefinition+ConstantColumnMapGenerator");
// get private readonly ColumnMap ConstantColumnMapGenerator._columnMap;
// of actual type internal class
// System.Data.Query.InternalTrees.SimpleCollectionColumnMap
Object columnMap = GetField(columnMapGenerator, "_columnMap");
AssertNonNullAndOfType(columnMap, "System.Data.Query.InternalTrees.SimpleCollectionColumnMap");
// get internal ColumnMap CollectionColumnMap.Element;
// of actual type internal class
// System.Data.Query.InternalTrees.RecordColumnMap
Object columnMapElement = GetProperty(columnMap, "Element");
AssertNonNullAndOfType(columnMapElement, "System.Data.Query.InternalTrees.RecordColumnMap");
// get internal ColumnMap[] StructuredColumnMap.Properties;
// array of internal abstract class
// System.Data.Query.InternalTrees.ColumnMap
Array columnMapProperties = GetProperty(columnMapElement, "Properties") as Array;
AssertNonNullAndOfType(columnMapProperties, "System.Data.Query.InternalTrees.ColumnMap[]");
Int32 n = columnMapProperties.Length;
Int32[] propertyPositions = new Int32[n];
for (Int32 i = 0; i < n; ++i)
{
// get value at index i in array
// of actual type internal class
// System.Data.Query.InternalTrees.ScalarColumnMap
Object column = columnMapProperties.GetValue(i);
AssertNonNullAndOfType(column, "System.Data.Query.InternalTrees.ScalarColumnMap");
//string colName = (string)GetProp(column, "Name");
// can be used for more advanced bingings
// get internal int ScalarColumnMap.ColumnPos;
Object columnPositionOfAProperty = GetProperty(column, "ColumnPos");
AssertNonNullAndOfType(columnPositionOfAProperty, "System.Int32");
propertyPositions[i] = (int)columnPositionOfAProperty;
}
return propertyPositions;
}
static object GetProperty(object obj, string propName)
{
PropertyInfo prop = obj.GetType().GetProperty(propName, BindingFlags.NonPublic | BindingFlags.Instance);
if (prop == null) throw EFChangedException();
return prop.GetValue(obj, new object[0]);
}
static object GetField(object obj, string fieldName)
{
FieldInfo field = obj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
if (field == null) throw EFChangedException();
return field.GetValue(obj);
}
static void AssertNonNullAndOfType(object obj, string fullName)
{
if (obj == null) throw EFChangedException();
string typeFullName = obj.GetType().FullName;
if (typeFullName != fullName) throw EFChangedException();
}
static InvalidOperationException EFChangedException()
{
return new InvalidOperationException("Entity Framework internals has changed, please review and fix reflection code");
}
Then I can modify the EntityToDatatable method as follows:
public static DataTable EntityToDatatable(this IQueryable query)
{
SqlConnection sqlConnection = null;
SqlCommand sqlCommand = null;
SqlDataAdapter sqlDataAdapter = null;
DataTable dataTable = null;
try
{
ObjectQuery objectQuery = (query as ObjectQuery);
ObjectContext objectContext = objectQuery.Context;
EntityConnection entityConnection = (objectContext.Connection as EntityConnection);
sqlConnection = new SqlConnection(entityConnection.StoreConnection.ConnectionString);
sqlCommand = new SqlCommand(objectQuery.ToTraceString(), sqlConnection);
foreach (var parameter in objectQuery.Parameters)
{
sqlCommand.Parameters.AddWithValue(parameter.Name, parameter.Value);
}
sqlDataAdapter = new SqlDataAdapter(sqlCommand);
dataTable = new DataTable();
sqlDataAdapter.Fill(dataTable);
// Get the mapping between the object property position and
// the SQL statment column position.
Int32[] propertyPositions = objectQuery.GetPropertyPositions();
// Create a column name to column position (ordinal) lookup.
Dictionary<String, Int32> mapColumnNameToColumnPosition = new Dictionary<string, int>();
// Populate the lookup.
for (Int32 i = 0; i < propertyPositions.Length; ++i)
{
mapColumnNameToColumnPosition.Add(dataTable.Columns[propertyPositions[i]].ColumnName, i);
}
// Get the object's property information.
PropertyInfo[] pi = query.GetType().GetGenericArguments()[0].GetProperties();
// Iterate through the lookup and change the position of the datatable columns.
// The order of the datatable columns will now correspond to the order of the object
// properties.
foreach (var map in mapColumnNameToColumnPosition)
{
// Change the column position.
dataTable.Columns[map.Key].SetOrdinal(map.Value);
// Change the column name.
dataTable.Columns[map.Key].ColumnName = pi[map.Value].Name;
}
return dataTable;
}
catch (Exception ex)
{
// Something went wrong and we're going to raise an exception...we
// might as well dispose of the datatable if it exists because it's
// not going to be used.
if (dataTable != null) dataTable.Dispose();
throw new Exception("IQueryable to DataTable conversion error.", ex);
}
finally
{
// Do some cleanup on objects that are no longer needed.
if (sqlDataAdapter != null) sqlDataAdapter.Dispose();
if (sqlCommand != null) sqlCommand.Dispose();
if (sqlConnection != null) sqlConnection.Dispose();
}
}

Resources