Spark combineByKey over reduceBykey using Java - apache-spark

I have the below dataset:
key value
---------------------------
key1,CLASS-A,YES,1
key2,CLASS-B,YES,2
key2,CLASS-B,YES,1
key1,CLASS-A,YES,4
key3,CLASS-C,DEFAULT,1
OUTPUT should look like:
key value
---------------------------
key1, CLASS-A,YES,5
key2, CLASS-B,YES,3
key3, CLASS-C,NO,1
While using reduceByKey to obtain the result , i found that whenever there is a key with only one value , in this case key3, the reduceByKey is not called as there is nothing to reduce against.And I get :
key value
---------------------------
key1, CLASS-A,YES,5
key2, CLASS-B,YES,3
key3, CLASS-C,DEAFULT,1
Can I achieve this using combineByKey in Spark (Java) .
What I tried so far :
reduceByKey(
new Function2<String, String, String>() {
#Override
public String call(String s1, String s2) throws Exception {
String[] vals1 = StringUtils.split(s1, ",");
String[] vals2 = StringUtils.split(s2, ",");
String jobStat1 = vals1[0];
String jobStat2 = vals2[0];
String reducedJobStat;
boolean s1 = jobStat1.equals("YES")
boolean s2 = jobStat2.equals("YES");
if (s1 || s2) {
reducedJobStat = "YES";
} else {
reducedJobStat = "NO";
}
return reducedJobStat;
}
}
)

the fundamental difference between reduceByKey and combineByKey in spark is that reduceByKey requires a function that takes a pair of values and returns a single value, whereas combineByKey allows for you to simultaneously transform your data and it requires three functions. The first is to create the new value type from the existing value type, the second adds an existing value type to a new value type, and the third adds to of the new value type.
The best example I have seen of combineByKey is at http://codingjunkie.net/spark-combine-by-key/
For your specific case, I'd recommend keeping it simple and using reduceByKey followed by mapValues to accomplish the desired transformation on key3. This might look something like:
reduced_rdd.mapValues(v => (v._1, if (v._2 == "DEFAULT") "NO" else v._2, v._3))

So , I got an alternate solution using combinerByKey. The code for reduceByKey looks simpler, but I am doing a mapValues after the reduceByKey(please look the question for reason) to get the result .
CombineByKey is fairly simple if we understand how it internally works .
Example using CombineByKey
Input :
key value
key1,CLASS-A,YES,1
key2,CLASS-B,YES,2
key2,CLASS-B,YES,1
key1,CLASS-A,YES,4
key3,CLASS-C,DEFAULT,1
//The CreateCombiner will initialise the 1st Key in the 1st partition . Here Lets divide the input into 2 partitions:
Partition 1: Partition 2:
key value key value
--------------------------- ---------------------------
key1, CLASS-A,YES,1 key1, CLASS-A,YES,4
key2, CLASS-B,YES,2 key3, CLASS-C,DEFAULT,1
key2, CLASS-B,YES,1
public class CreateCombiner implements Function<String, String> {
#Override
public String call(String value) { //value here is "CLASS-A,YES,1"
String jobStatus = value.split(",")[0];
if (jobStatus.equals("YES")
|| jobStatus.equals("DEFAULT") {
return "YES"+ " " + value.split(" ")[1] + " " + value.split(" ")[2];
} else {
return "NO" + " " + value.split(" ")[1] + " " + value.split(" ")[2];
}
}
}
When the Key1 in 1st partition is encounterd, the CreateCombiner will initialise that key's. (key1 here) value,In our case we change the value(2nd string(YES/NO/DEFAULT)).
Becase in my usecase I want to change all "DEFAULT" to "YES" .
It replaces all the YES and DEFAULT strings to YES and otherwise to NO. Now Same for Key2 in the 1st partition .
Again when it finds key2 in the 1st partition , the MergeValue class is called. It will merge the values . So here Key2 has 2 values(CLASS-B,YES,2 and CLASS-B,YES,1). It merges both.
like (key2,CLASS-B,YES,3)
The MergeCombiner takes the combiners (tuples) created on each partition and merges them together. So in my case the logic is same as in MergeValue.
public class MergeValue implements Function2<String, String, String> {
// MergeCombiner will decide the jobStatus and add the outCount and lbdCount.
// This is a Merging function that takes a value and merges it into the previously collecte value(s).
#Override
public String call(String v1, String v2) throws Exception {
String[] vals1 = StringUtils.split(v1, ",");
String[] vals2 = StringUtils.split(v2, ",");
String jobStat1 = vals1[0];
String jobStat2 = vals2[0];
String reducedJobStat;
boolean stat1Process = (jobStat1.equals("YES"))
|| (jobStat1.equals("DEFAULT"));
boolean stat2Process = (jobStat2.equals("YES"))
|| (jobStat2.equals("DEFAULT"));
if (stat1Process || stat2Process) {
reducedJobStat = "YES";
} else {
reducedJobStat = "NO";
}
int outCount = Integer.parseInt(vals1[1]) + Integer.parseInt(vals2[1]);
int lbdCount = Integer.parseInt(vals1[2]) + Integer.parseInt(vals2[2]);
return reducedJobStat + " " + Integer.toString(outCount) + " " + Integer.toString(lbdCount);
}
}
public class MergeCombiner implements Function2<String, String, String> {
// This fucntion combines the merged values together from MergeValue.
// Basically this function takes the new values produced at the partition level and combines them until we end up
// with one singular value.
#Override
public String call(String v1, String v2) throws Exception {
String[] vals1 = StringUtils.split(v1, ",");
String[] vals2 = StringUtils.split(v2, ",");
String jobStat1 = vals1[0];
String jobStat2 = vals2[0];
String reducedJobStat;
//Here we decide the jobStatus from 2 combiners , if both of them are complete ie jobStat1 and jobStat2 is COMP
// LETE, then the Status is marked as complete.
boolean stat1Process = (jobStat1.equals("YES");
boolean stat2Process = (jobStat2.equals("YES");
if (stat1Process || stat2Process) {
reducedJobStat = "YES";
} else {
reducedJobStat = "YES";
}
int outCount = Integer.parseInt(vals1[1]) + Integer.parseInt(vals2[1]);
int lbdCount = Integer.parseInt(vals1[2]) + Integer.parseInt(vals2[2]);
return reducedJobStat + " " + Integer.toString(outCount) + " " + Integer.toString(lbdCount);
}
Call to combineByKey
combineByKey(new CreateCombiner(), new MergeValue(), new MergeCombiner());
The same code Inmplemented using reduceByKey:
reduceByKey(
new Function2<String, String, String>() {
#Override
public String call(String s1, String s2) throws Exception {
String[] vals1 = StringUtils.split(s1, " ");
String[] vals2 = StringUtils.split(s2, " ");
String jobStat1 = vals1[0];
String jobStat2 = vals2[0];
String reducedJobStat;
boolean stat1Process = (jobStat1.equals("YES")) ||
(jobStat1.equals("DEFAULT");
boolean stat2Process = (jobStat2.equals("YES")) ||
(jobStat2.equals("DEFAULT");
if (stat1Process || stat2Process) {
reducedJobStat = "YES";
} else {
reducedJobStat = "NO";
}
int outCount = Integer.parseInt(vals1[1]) + Integer.parseInt(vals2[1]);
int lbdCount = Integer.parseInt(vals1[2]) + Integer.parseInt(vals2[2]);
return reducedJobStat + " " + Integer.toString(outCount) + " " + Integer.toString(lbdCount);
}
} ).mapValues(new Function<String, String>() {
#Override
public String call(String s) throws Exception {
String jobStatus = s.split(" ")[0];
if (jobStatus.equals("YES")
|| jobStatus.equals("DEFAULT") {
return "YES" + " " + s.split(" ")[1] + " " + s.split(" ")[2];
} else {
return "NO" + " " + s.split(" ")[1] + " " + s.split(" ")[2];
}
}
});

Related

Issue with splitting a string

For some reason, I can't get the split function to work.
I'm trying to compare the second word in the action string to the target string. What am I doing wrong?
String action = "Test Hello";
String target = "Hello";
void setup() {
}
void draw() {
String[] split = split(action, ' ');
String newScene = split[1];
boolean result = (newScene == target);
println("is " + newScene + " == " + target + ": " + result);
}
Here is a Java way of doing this:
String action = "Test Hello";
String target = "Hello";
if (action.split(" ")[1].equals(target)) {
System.out.println("MATCH");
}

Using a hashmap with int as key and need to change it to use long

I was given some sample code by my instructor for HashEntry class and HashMap class. I had to implement the get and put method in the HashMap for the standard probing and then linear and quadratic. I have all this working fine, I am able to get and put with any of the probing methods. The next step was to read in a .csv file and parse it so the first column is the key and the remaining columns are the rows. This all works great until my key value from the .csv goes above the valid int value. My question is how can I change the provided code to use a long as the key instead of an int.
public class HashEntry {
private int key;
private String value;
HashEntry(int key, String value) {
this.key = key;
this.value = value;
}
public int getKey() {
return key;
}
public String getValue() {
return value;
}
public void setValue(String val) {
this.value = val;
}
}
HashMap
public class HashMap {
private final static int TABLE_SIZE = 1900000;
HashEntry[] table;
HashMap() {
table = new HashEntry[TABLE_SIZE];
for (int i = 0; i < TABLE_SIZE; i++)
table[i] = null;
}
public String get(int key) {
int hash = (key % TABLE_SIZE);
while (table[hash] != null && table[hash].getKey() != key)
hash = (7 * hash + 1) % TABLE_SIZE;
if (table[hash] == null)
return "There is no value at this key";
else
return table[hash].getValue();
}
public void put(int key, String value) {
int hash = (key % TABLE_SIZE);
while (table[hash] != null && table[hash].getKey() != key)
hash = (7 * hash + 1) % TABLE_SIZE;
table[hash] = new HashEntry(key, value);
}
public void linearprobeput(int key, String value){
int i = 0;
int hash = (key % TABLE_SIZE);
//System.out.println("The hash is " + hash+ "\n");
while (table[hash] != null && table[hash].getKey() != key)
{
hash = (hash + i) % TABLE_SIZE;
i++;
//printing was to verify collisions were being managed correctly
//System.out.println("Their was a collision now trying with hash'"
//+ hash +" and an i value of "+ i+ "'\n");
}
table[hash] = new HashEntry(key, value);
}
public String linearprobeget(int key){
int hash = (key % TABLE_SIZE);
int i = 0;
while (table[hash] != null && table[hash].getKey() != key)
{
hash = (hash + i) % TABLE_SIZE;
i++;
}
if (table[hash] == null)
return "There is no value at this key";
else
return table[hash].getValue();
}
public void quadraticprobeput(int key, String value){
int i = 0;
int hash = (key % TABLE_SIZE);
//System.out.println("The hash is " + hash+ "\n");
while (table[hash] != null && table[hash].getKey() != key)
{
hash = (hash + (i*i)) % TABLE_SIZE;
i++;
//printing was to verify collisions were being managed correctly
//System.out.println("Their was a collision now trying with hash'"
//+ hash +" and an i value of "+ i+ "'\n");
}
table[hash] = new HashEntry(key, value);
}
public String quadraticprobeget(int key){
int hash = (key % TABLE_SIZE);
int i = 0;
while (table[hash] != null && table[hash].getKey() != key)
{
hash = (hash + (i*i)) % TABLE_SIZE;
i++;
}
if (table[hash] == null)
return "There is no value at this key";
else
return table[hash].getValue();
}
}
Main
HashMap upchm = new HashMap();
BufferedReader in = new BufferedReader
(new FileReader("UPCtest.csv"));
//Integer a = null;
String str=null;
ArrayList<String> lines = new ArrayList<String>();
//lines.split(",")[1]+
while((str = in.readLine()) != null){
//lines.add(str);
String[] upc= str.split(",");
Integer val = Integer.valueOf(upc[0]);
upchm.quadraticprobeput(val, upc[1]+upc[2]);
System.out.println("UPC = " + val + " Description "+upc[1]+upc[2]);
}
//change arraylist to array
//String[] upc = lines.toArray(new String[lines.size()]);
in.close();
System.out.println("\n");
System.out.println("The description for the product with upc 123 is " + upchm.quadraticprobeget(123));
System.out.println("The description for the product with upc 10344 is " + upchm.quadraticprobeget(10344));
Sample of some of the lines from the .csv
79,,INDIANA LOTTO 93,,treo 700w 123,,Wrsi Riversound cafe cd
161,,Dillons/Kroger Employee Coupon ($1.25 credit)
2158242769,288/1.12Z,GREEN SUGAR COOKIES4276 2158561631,,HOT COCOA
W/BKMK 2158769549,njhjhn,gjfhjbgkj 2160500567,2.25 oz (64)g,Dollar
Bar Rich Raspberry 2172307284,,Mixed seasonal flower bouquet
2177000074,,4 way 13 AMP Extension Lead (Wilkinson UK) 2184000098,21
oz,Christopher's Assorted Fruit Jellies 2187682888,,fairway
15400021142,9 Z,WF BOWL CLEANER (JAR 15400021159,8 Z,WF ANTIBAC LIQ
SOAP 15400021166,3 RL,WF DECORATOR VALUE 15400021173,64 Z,WF CLEAR
AMMONIA 15400021210,128 Z,WF FAB SOFT 15400021319,28 Z,WF DEGREAS
ULT DISH 15400021326,28 Z,WF LEMON ULTRA DISH 15400021340,28 Z,WF
ANTIBACT DISH LIQ 15400021364,65 Z,WF AUTO DISH DETERGE
You have to use long key instead of int key and cast a type when you calculate a bucket in the table:
HashEntry class
public class HashEntry {
private long key;
private String value;
}
HashMap class
public class HashMap {
private static final int TABLE_SIZE = 1900000;
private final HashEntry[] table;
public HashMap() {
// all elements are null by default
table = new HashEntry[TABLE_SIZE];
}
public String get(long key) {
int bucket = getBucket(key);
while (table[bucket] != null && table[bucket].getKey() != key) {
bucket = (7 * bucket + 1) % TABLE_SIZE;
}
return getValueByBucket(bucket, key);
}
public void put(long key, String value) {
int bucket = getBucket(key);
while (table[bucket] != null && table[bucket].getKey() != key) {
bucket = (7 * bucket + 1) % TABLE_SIZE;
}
table[bucket] = new HashEntry(key, value);
}
public void linearprobeput(long key, String value) {
int i = 0;
int bucket = getBucket(key);
//System.out.println("The hash is " + hash+ "\n");
while (table[bucket] != null && table[bucket].getKey() != key) {
bucket = (bucket + i) % TABLE_SIZE;
i++;
//printing was to verify collisions were being managed correctly
//System.out.println("Their was a collision now trying with hash'"
//+ hash +" and an i value of "+ i+ "'\n");
}
table[bucket] = new HashEntry(key, value);
}
public String linearprobeget(long key) {
int i = 0;
int bucket = getBucket(key);
while (table[bucket] != null && table[bucket].getKey() != key) {
bucket = (bucket + i) % TABLE_SIZE;
i++;
}
return getValueByBucket(bucket, key);
}
public void quadraticprobeput(long key, String value) {
int i = 0;
int bucket = getBucket(key);
//System.out.println("The hash is " + hash+ "\n");
while (table[bucket] != null && table[bucket].getKey() != key) {
bucket = (bucket + (i * i)) % TABLE_SIZE;
i++;
//printing was to verify collisions were being managed correctly
//System.out.println("Their was a collision now trying with hash'"
//+ hash +" and an i value of "+ i+ "'\n");
}
table[bucket] = new HashEntry(key, value);
}
public String quadraticprobeget(long key) {
int i = 0;
int bucket = getBucket(key);
while (table[bucket] != null && table[bucket].getKey() != key) {
bucket = (bucket + (i * i)) % TABLE_SIZE;
i++;
}
return getValueByBucket(bucket, key);
}
private static int getBucket(long key) {
// this is safe, because key % TABLE_SIZE < TABLE_SIZE which is int
return (int)(key % TABLE_SIZE);
}
private String getValueByBucket(int bucket, long key) {
return table[bucket] == null ? "There is no value at key '" + key + '\'' : table[bucket].getValue();
}
}
I think, and java.lang.HashMap uses it as well, that it is better to move HashEntry into HashMap class:
public class HashMap {
private static final int TABLE_SIZE = 1900000;
private final Entry[] table;
public HashMap() {
// all elements are null by default
table = new Entry[TABLE_SIZE];
}
//...
private static final class Entry {
private long key;
private String value;
}
}
Second, it is better to throw an exception with There is no value at key or return null. What if you have: map.put(666, "There is no value at key") - when you get this key, how do you know it this key exists or not?!

How to search specific string form list in multithreaded environment.?

Suppose i have a 4 List which contains String object.
Example:
List<String> str1;
List<String> str2;
List<String> str3;
List<String> str4;
Suppose below value are stored in List str1, str2, str3 and str4 respectively.
str1 = [i, need , help.]
str2 = [This , is , a , good , program.]
str3 = [i, need ,solution.]
str4 = [i, need , solution, using ,multi-thread,concept.]
Now i need to search a string "good" from the list using a multi-threaded concept. Where for each list we will have an independent thread running in parallel and as soon as any thread finds the string name "good" all the other thread will get destroyed and on console we print the running Thread name and the List in which the String has been found.
I need a solution from someone since this is new to me and I have no idea how to get this done.
In Java 8 you could do it like this:
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class MultithreadedSearch {
public static void main(String[] args) {
List<String> str1 = Arrays.asList("i ", "need ", "help.");
List<String> str2 = Arrays.asList("This ", "is ", "a ", "good ", "program.");
List<String> str3 = Arrays.asList("i", "need ", "solution.");
List<String> str4 = Arrays.asList("i ", "need ", "solution ", "using ", "multi-thread ", "concept.");
CompletableFuture<Void> cf1 = CompletableFuture.runAsync(search(str1, "good"));
CompletableFuture<Void> cf2 = CompletableFuture.runAsync(search(str2, "good"));
CompletableFuture<Void> cf3 = CompletableFuture.runAsync(search(str3, "good"));
CompletableFuture<Void> cf4 = CompletableFuture.runAsync(search(str4, "good"));
CompletableFuture.anyOf(cf1, cf2, cf3, cf4).join();
}
private static Runnable search(List<String> list, String searchString) {
return () -> list.stream().filter(x -> x.trim().equals(searchString)).findFirst().ifPresent(x -> {
System.out.println("Thread: " + Thread.currentThread().getName());
System.out.println("List: " + list);
});
}
}
You have one CompletableFuture for each list of strings, executing a Runnable that performs the search, and with CompletableFuture.anyOf, the first CompletableFuture finding the search string wins.
[EDIT: Java 7]
As you asked, in Java 7 you could use a ForkJoinPool, but it is somewhat less elegant:
public class MultithreadedSearch2 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
List<String> str1 = Arrays.asList(" ", "i ", "need ", "help.");
List<String> str2 = Arrays.asList("This ", "is ", "a ", " ", "program.");
List<String> str3 = Arrays.asList("i", "need ", "solution.");
List<String> str4 = Arrays.asList("i ", "need ", "solution ", "using ", "multi-thread ", "concept.", " ");
Callable<Result> t1 = search(str1, "good");
Callable<Result> t2 = search(str2, "good");
Callable<Result> t3 = search(str3, "good");
Callable<Result> t4 = search(str4, "good");
ForkJoinPool executor = new ForkJoinPool();
executor.invokeAny(Arrays.asList(t1, t2, t3, t4)).output();
}
private static Callable<Result> search(final List<String> list, final String searchString) {
return new Callable<Result>() {
#Override
public Result call() throws Exception {
for (String s : list) {
if (s.trim().equals(searchString)) {
return new Result(Thread.currentThread(), list);
}
}
throw new Exception("nothing found");
}
};
}
private static class Result {
private final Thread thread;
private final List<String> list;
public Result(Thread thread, List<String> list) {
this.thread = thread;
this.list = list;
}
public void output() {
System.out.println("Thread: " + thread.getName());
System.out.println("List: " + list);
}
}
}

Update Excel Cell using OLEDB

I want to update 1 cell in an Excel (xlsx) file using OLEDB.
I have attached my code.
The first time you run, it fills in the values because INSERT is working.
The second time you run, it APPENDS the values because the UPDATE fails, and my Catch performs an INSERT. My goal is to have the UPDATE command work. When the UPDATE command executes, I get an error message:
No value given for one or more required parameters.
at System.Data.OleDb.OleDbCommand.ExecuteCommandTextErrorHandling(OleDbHResult hr)
at System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBPARAMS dbParams, Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior behavior, Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method)
at System.Data.OleDb.OleDbCommand.ExecuteNonQuery()
at ConsoleApp3.Program.InsertCSVIntoSheet(String excelPath, String sheet, String csvPath) in C:\Users\jbendler.atlab\source\repos\ConsoleApp3\Program.cs:line 175
This code comes from a demo Console App. This is the program.cs file.
The main part of the code is located at the bottom of the InsertCSVIntoSheet method. The output xlsx file is simply a new workbook, unedited. The input file is simply a text file, named with a .csv extension, that contains the following separated by carriage-return/linefeed - so the file has 5 lines with one character per line:
ABCDE
Thanks.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
InsertCSVIntoSheet(#"c:\temp\book1.xlsx", "NewSheet", #"c:\temp\test.csv");
}
private static void InsertCSVIntoSheet(string excelPath, string sheet, string csvPath)
{
int column;
int row;
int pos;
bool done;
char readUntilChar;
string csvData;
string columnName;
string cell;
string excelSheetName;
List<Tuple<int, int, object>> values = new List<Tuple<int, int, object>>();
string connectionString = CreateOleDbConnectionStringForExcel(excelPath);
OleDbCommand oleDbCommand = new OleDbCommand();
decimal decimalTest;
DateTime dateTimeTest;
int status;
int numColumns;
// Put CSV in to row/column/value Tuples
using (StreamReader reader = new StreamReader(csvPath))
{
csvData = reader.ReadToEnd();
row = 1;
// Split the csv data by new line
foreach (string line in csvData.Split(new string[] { "\r\n" }, StringSplitOptions.None))
{
if (!string.IsNullOrEmpty(line))
{
column = 1;
pos = 0;
cell = string.Empty;
// Split each line by ',' to get each cell. A value wrapped in '"' can include a ','
while (pos < line.Length)
{
cell = string.Empty;
// Check the first character. If it is a '"' then we assume the cell is surrounded
// in '"' and do NOT include the '"' in the output to the excel cell.
if (line[pos] == '"')
{
readUntilChar = '"';
pos++;
}
else
{
readUntilChar = ',';
}
done = line[pos] == readUntilChar;
if (line[pos] == '"')
{
// Skip over second '"' for a blank ("")
pos++;
}
while (!done)
{
cell += line[pos++];
if (pos == line.Length || line[pos] == readUntilChar)
{
if (readUntilChar == '"')
{
// Skip the '"'
pos++;
}
done = true;
}
}
// Skip over the ','
pos++;
if (!string.IsNullOrEmpty(cell))
{
// Test the data to determine the type (check for decimal and DateTime).
if (decimal.TryParse(cell, out decimalTest))
{
values.Add(new Tuple<int, int, object>(row, column, decimalTest));
}
else if (DateTime.TryParse(cell, out dateTimeTest))
{
values.Add(new Tuple<int, int, object>(row, column, dateTimeTest));
}
else
{
// Write out the value as a string
values.Add(new Tuple<int, int, object>(row, column, cell));
}
}
column++;
}
}
row++;
}
}
using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Suppress))
{
excelSheetName = GetExcelSheetNames(connectionString).Where(n => n.ToUpper().StartsWith(sheet.ToUpper())).FirstOrDefault();
//Set the connection string to recognize the header and to operate in Update mode(IMEX= 0)
using (OleDbConnection oleDbConnection = new OleDbConnection(connectionString.Replace("IMEX=1", "IMEX=0")))
{
oleDbConnection.Open();
oleDbCommand = new OleDbCommand();
oleDbCommand.Connection = oleDbConnection;
oleDbCommand.CommandType = CommandType.Text;
if (excelSheetName != null)
{
// Delete Sheet
oleDbCommand.CommandText = "DROP TABLE [" + sheet + "]";
status = oleDbCommand.ExecuteNonQuery();
}
else
{
excelSheetName = sheet + "$";
}
numColumns = values.Max(v => v.Item2);
oleDbCommand.CommandText = "CREATE TABLE [" + sheet + "](";
for (int index = 0; index < numColumns; index++)
{
oleDbCommand.CommandText += "Column" + index.ToString() + " CHAR(255), ";
}
oleDbCommand.CommandText = oleDbCommand.CommandText.Substring(0, oleDbCommand.CommandText.Length - 2) + ")";
status = oleDbCommand.ExecuteNonQuery();
}
using (OleDbConnection oleDbConnection = new OleDbConnection(connectionString.Replace("IMEX=1", "IMEX=0")))
{
oleDbConnection.Open();
oleDbCommand.Connection = oleDbConnection;
// Write out new values
foreach (Tuple<int, int, object> tuple in values)
{
try
{
columnName = GetExcelColumnName(tuple.Item2) + (tuple.Item1 + 1).ToString();
oleDbCommand.CommandText = "UPDATE [" + excelSheetName + columnName + ":" + columnName + "] SET " + "F1" + " = '" + tuple.Item3.ToString() + "'";
status = oleDbCommand.ExecuteNonQuery();
}
catch (OleDbException oledbex)
{
oleDbCommand.CommandText = "INSERT INTO [" + excelSheetName + "] VALUES ('" + tuple.Item3.ToString() + "')";
status = oleDbCommand.ExecuteNonQuery();
}
}
}
}
}
private static List<string> GetExcelSheetNames(string connectionString)
{
OleDbConnection oleDbConnection = null;
DataTable dataTable = null;
List<string> excelSheetNames = null;
using (oleDbConnection = new OleDbConnection(connectionString))
{
oleDbConnection.Open();
dataTable = oleDbConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
}
if (dataTable != null)
{
excelSheetNames = new List<string>(dataTable.Rows.Cast<DataRow>().Where(r => r["TABLE_NAME"].ToString().EndsWith("$") || r["TABLE_NAME"].ToString().EndsWith("$'")).Select(r => r["TABLE_NAME"].ToString().ToUpper()));
}
return excelSheetNames;
}
private static string CreateOleDbConnectionStringForExcel(string sourceFile)
{
var fileInfo = new FileInfo(sourceFile);
switch (fileInfo.Extension.ToUpper())
{
case ".XLS":
return string.Format("Provider=Microsoft.ACE.OLEDB.12.0;;Data Source='{0}';Extended Properties='Excel 8.0;HDR=No;IMEX=1'", sourceFile);
case ".XLSX":
case ".XLSM":
return string.Format("Provider=Microsoft.ACE.OLEDB.12.0;;Data Source='{0}';Extended Properties='Excel 12.0;HDR=No;IMEX=1'", sourceFile);
default:
throw new NotSupportedException("File type not supported.");
}
}
private static string GetExcelColumnName(int columnNumber)
{
string columnName = String.Empty;
int dividend = columnNumber;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
dividend = (int)((dividend - modulo) / 26);
}
return columnName;
}
}
}

Changing the constraints in a Container object

In Java 8, the Container class has an void add(Component comp, Object constraints) method that adds the component with a constraints information. I want to build a GUI with three panels, where pressing a button would result in switching the constraint information of the components that do not include the button object. How is it possible to switch the constraint information?
EDIT:
I tried the following:
private Map<SpecUITitlePanel, GridBagConstraints> constraints = new Hashtable<SpecUITitlePanel, GridBagConstraints>();
[…]
switchPanelsButton.setText( "Switch panels");
switchPanelsButton.addActionListener( new java.awt.event.ActionListener() {
public void actionPerformed( final java.awt.event.ActionEvent event) {
switchPanelsActionPerformed( event);
}
[…]
private void switchPanelsActionPerformed( final java.awt.event.ActionEvent event) {
boolean swapped = false;
final GridBagLayout layout = (GridBagLayout) getLayout();
final Iterator<SpecUITitlePanel> keysIter = constraints.keySet().iterator();
// summaryPanel, testPanel
while (keysIter.hasNext() && layout != null) {
final SpecUITitlePanel key = keysIter.next();
final String title = key.getTitle();
final Iterator<SpecUITitlePanel> keysIter2 = constraints.keySet().iterator();
while (keysIter2.hasNext()) {
final SpecUITitlePanel key2 = keysIter2.next();
final String title2 = key2.getTitle();
if (!title.equals( title2)) {
if (!title.contains( BUTTON_PANEL_TITLE) && !title2.contains( BUTTON_PANEL_TITLE)) {
// swap components
String message = "component = " + title + ", "
+ constraints.get( key) + "; component2 = " + title2
+ ", " + constraints.get( key2);
System.out.println( message);
final GridBagConstraints value = constraints.get( key);
final GridBagConstraints value2 = constraints.get( key2);
constraints.put(key, value2);
layout.setConstraints( key, value2);
constraints.put(key2, value);
layout.setConstraints( key2, value);
swapped = true;
message = "component = " + title + ", "
+ constraints.get( key) + "; component2 = " + title2
+ ", " + constraints.get( key2);
System.out.println( message);
}
}
}
}
if (swapped) {
repaint();
}
}
The relevant part of the output is
component = Test, java.awt.GridBagConstraints#5179288b; component2 = tna.rads.main_panel.violation_summary_panel, java.awt.GridBagConstraints#f1a7ed2
component = Test, java.awt.GridBagConstraints#f1a7ed2; component2 = tna.rads.main_panel.violation_summary_panel, java.awt.GridBagConstraints#5179288b

Resources