In the restbucks project, an order has a private list of line items. I can't figure out how this field is exposed via rest api when getting a single order. It has no public getter or anything. Is it the mixins?
#Data, #NoArgsConstructor, #AllArgsConstructor, #EqualsAndHashCode are Lombok annotations, that are used to auto-generate a boilerplate code.
#Data
#Entity
#NoArgsConstructor(force = true)
#AllArgsConstructor
#EqualsAndHashCode(callSuper = false)
public class LineItem extends AbstractEntity {
private final String name;
private final int quantity;
private final Milk milk;
private final Size size;
private final MonetaryAmount price;
public LineItem(String name, MonetaryAmount price) {
this(name, 1, Milk.SEMI, Size.LARGE, price);
}
}
You can compare this code with delomboked one (welcome to Lombok-funs club )):
#Entity
public class LineItem extends AbstractEntity {
private final String name;
private final int quantity;
private final Milk milk;
private final Size size;
private final MonetaryAmount price;
public LineItem(String name, MonetaryAmount price) {
this(name, 1, Milk.SEMI, Size.LARGE, price);
}
public LineItem(String name, int quantity, Milk milk, Size size, MonetaryAmount price) {
this.name = name;
this.quantity = quantity;
this.milk = milk;
this.size = size;
this.price = price;
}
public LineItem() {
this.name = null;
this.quantity = 0;
this.milk = null;
this.size = null;
this.price = null;
}
public String getName() {
return this.name;
}
public int getQuantity() {
return this.quantity;
}
public Milk getMilk() {
return this.milk;
}
public Size getSize() {
return this.size;
}
public MonetaryAmount getPrice() {
return this.price;
}
public String toString() {
return "LineItem(name=" + this.getName() + ", quantity=" + this.getQuantity() + ", milk=" + this.getMilk() + ", size=" + this.getSize() + ", price=" + this.getPrice() + ")";
}
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof LineItem)) return false;
final LineItem other = (LineItem) o;
if (!other.canEqual((Object) this)) return false;
final Object this$name = this.getName();
final Object other$name = other.getName();
if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
if (this.getQuantity() != other.getQuantity()) return false;
final Object this$milk = this.getMilk();
final Object other$milk = other.getMilk();
if (this$milk == null ? other$milk != null : !this$milk.equals(other$milk)) return false;
final Object this$size = this.getSize();
final Object other$size = other.getSize();
if (this$size == null ? other$size != null : !this$size.equals(other$size)) return false;
final Object this$price = this.getPrice();
final Object other$price = other.getPrice();
if (this$price == null ? other$price != null : !this$price.equals(other$price)) return false;
return true;
}
public int hashCode() {
final int PRIME = 59;
int result = 1;
final Object $name = this.getName();
result = result * PRIME + ($name == null ? 43 : $name.hashCode());
result = result * PRIME + this.getQuantity();
final Object $milk = this.getMilk();
result = result * PRIME + ($milk == null ? 43 : $milk.hashCode());
final Object $size = this.getSize();
result = result * PRIME + ($size == null ? 43 : $size.hashCode());
final Object $price = this.getPrice();
result = result * PRIME + ($price == null ? 43 : $price.hashCode());
return result;
}
protected boolean canEqual(Object other) {
return other instanceof LineItem;
}
}
Related
Not working Query :
select lookup(city, state, tax,'addresslookup')
from (select distinct city, state, tax
from open_glory.addylookup) a
Working Query (without distinct):
select lookup(city, state, tax,'addresslookup')
from (select city, state, tax
from open_glory.addylookup) a
Any help would be appreciated.
UDF code:
Not working Query :
select lookup(city, state, tax,'addresslookup')
from (select distinct city, state, tax
from open_glory.addylookup) a
Working Query (without distinct):
select lookup(city, state, tax,'addresslookup')
from (select city, state, tax
from open_glory.addylookup) a
Any help would be appreciated.
UDF code:
public class Lookup extends GenericUDF {
private static String delimiter = "|";
private ConcurrentHashMap < String, HashMap < String, String >> fileMap = new ConcurrentHashMap < String, HashMap < String, String >> ();
protected String loggedInUser;
protected String loggedInApplication;
private transient GenericUDFUtils.StringHelper returnHelper;
private transient StringConverter[] stringConverter;
private static final Logger LOG = LoggerFactory.getLogger(Lookup.class.getName());
#Override
public ObjectInspector initialize(ObjectInspector[] arguments)
throws UDFArgumentException {
if (arguments.length < 2) {
throw new UDFArgumentLengthException(
"lookup takes 2 or more arguments");
}
stringConverter = new StringConverter[arguments.length];
for (int i = 0; i < arguments.length; i++) {
if (arguments[0].getCategory() != Category.PRIMITIVE) {
throw new UDFArgumentException(
"lookup only takes primitive types");
}
stringConverter[i] = new PrimitiveObjectInspectorConverter.StringConverter(
(PrimitiveObjectInspector) arguments[i]);
}
setLoggedInUser();
returnHelper = new GenericUDFUtils.StringHelper(
PrimitiveCategory.STRING);
LOG.info("initialize successful");
return PrimitiveObjectInspectorFactory.writableStringObjectInspector;
}
private void setLoggedInUser() {
if (loggedInUser == null) {
loggedInUser = SessionState.get().getUserName();
if (loggedInUser != null) {
int idx = loggedInUser.indexOf('.');
loggedInApplication = idx > -1 ? loggedInUser.substring(0, idx) : null;
}
}
}
private void initMap(String f) {
LOG.info("initMap involked");
if (loggedInApplication == null)
throw new NullPointerException(
"Unable to retrieve application name from user.");
String filePath = "/basepath/" + loggedInApplication.toLowerCase() + "/" + f +
".txt";
String line = null;
try {
LOG.info("filePath =" + filePath);
FileSystem fs = FileSystem.get(new Configuration());
FSDataInputStream in = fs.open(new Path(filePath));
BufferedReader br = new BufferedReader(new InputStreamReader( in ));
HashMap < String, String > map = new HashMap < String, String > ();
while ((line = br.readLine()) != null) {
// ignore comment lines
if (line.startsWith("#")) {
continue;
}
String[] strs = line.split("\t");
if (strs.length == 2) {
map.put(strs[0].toUpperCase().trim(), strs[1].trim());
} else if (strs.length > 2) {
map.put(getKey(strs), strs[strs.length - 1].trim());
}
}
fileMap.put(f, map);
br.close();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
public Text getValue(String s, String f) {
initMap(f);
HashMap < String, String > map = fileMap.get(f);
LOG.info("getValue() fileMap =" + fileMap);
String v = map.get(s);
return v == null ? null : new Text(v);
}
#Override
public Object evaluate(DeferredObject[] arguments) throws HiveException {
String val = buildVal(arguments);
String lookupFile = (String) stringConverter[arguments.length - 1].convert(arguments[arguments.length - 1].get());
Text returnVal = getValue(val.toUpperCase(), lookupFile.toLowerCase());
return returnVal == null ? null : returnHelper.setReturnValue(returnVal.toString());
}
#Override
public String getDisplayString(String[] arg0) {
return "lookup()";
}
private String buildVal(DeferredObject[] arguments) throws HiveException {
StringBuilder builder = new StringBuilder();
int cnt = arguments.length - 1;
for (int i = 0; i < cnt; i++) {
builder.append((String) stringConverter[i].convert(arguments[i].get()));
if (i < cnt - 1) {
builder.append(delimiter);
}
}
return builder.toString();
}
private String getKey(String[] strs) {
StringBuilder builder = new StringBuilder();
int cnt = strs.length - 1;
for (int i = 0; i < cnt; i++) {
builder.append(strs[i].toUpperCase().trim());
if (i < cnt - 1) {
builder.append(delimiter);
}
}
return builder.toString();
}
}
I want to deserialize a JSON array to a singly linked list in Java.
The definition of singly linked list is as the following:
public class SinglyLinkedListNode<T> {
public T value;
public SinglyLinkedListNode next;
public SinglyLinkedListNode(final T value) {
this.value = value;
}
}
How to deserialize a JSON string such as [1,2,3,4,5] in to a singly linked list?
public void typeReferenceTest() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
final ArrayList<Integer> intArray = objectMapper.readValue("[1,2,3,4,5]",
new TypeReference<ArrayList<Integer>>() {});
System.out.println(intArray);
// How to achieve this?
final ArrayList<Integer> intList = objectMapper.readValue("[1,2,3,4,5]",
new TypeReference<SinglyLinkedListNode<Integer>>() {});
System.out.println(intList);
}
Moreover, I want the SinglyLinkedListNode to be a first-class citizen the same as ArrayList, which can be used in all kinds of combinations, such as HashSet<SinglyLinkedListNode<Integer>>, SinglyLinkedListNode<HashMap<String, Integer>>.
For example, what happens if I want to deserialize [[1,2,3], [4,5,6]] into a ArrayList<SinglyLinkedListNode<Integer>> ?
As far as I know, a customized deserializer extending JsonDeserializer is not enough to do this.
When you want it to be deserialized to ArrayList<SinglyLinkedListNode<Integer>> for example. Your code specifies that is the type that expected. Therefore it should if a deserializer for SinglyLinkedListNode<Integer> is regeistered it will succeed.
From the jackson-user google group I get the right answer from #Tatu Saloranta.
The answer is simple: just implement the java.util.List interface, and Jackson will automatically serialize/deserialize between JSON array and SinglyLinkedListNode.
So I implement the java.util.List interface for SinglyLinkedListNode, the code is as the following:
import java.util.*;
import java.util.function.Consumer;
/**
* Singly Linked List.
*
* <p>As to singly linked list, a node can be viewed as a single node,
* and it can be viewed as a list too.</p>
*
* #param <E> the type of elements held in this collection
* #see java.util.LinkedList
*/
public class SinglyLinkedListNode<E>
extends AbstractSequentialList<E>
implements Cloneable, java.io.Serializable {
public E value;
public SinglyLinkedListNode<E> next;
/**
* Constructs an empty list.
*/
public SinglyLinkedListNode() {
value = null;
next = null;
}
/**
* Constructs an list with one elment.
*/
public SinglyLinkedListNode(final E value) {
this.value = value;
next = null;
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* #param c the collection whose elements are to be placed into this list
* #throws NullPointerException if the specified collection is null
*/
public SinglyLinkedListNode(Collection<? extends E> c) {
this();
addAll(c);
}
/**
* Links e as last element.
*/
void linkLast(E e) {
final SinglyLinkedListNode<E> l = last();
final SinglyLinkedListNode<E> newNode = new SinglyLinkedListNode<>(e);
if (l == null)
this.value = e;
else
l.next = newNode;
modCount++;
}
/**
* Inserts element e before non-null Node succ.
*/
void linkBefore(E e, SinglyLinkedListNode<E> succ) {
assert succ != null;
final SinglyLinkedListNode<E> prev = this.previous(succ);
final SinglyLinkedListNode<E> newNode = new SinglyLinkedListNode<>(e);
if (prev == null)
this.value = e;
else
prev.next = newNode;
modCount++;
}
/**
* Return the node before x.
*
* #param x current node
* #return the node before x
*/
private SinglyLinkedListNode<E> previous(final SinglyLinkedListNode<E> x) {
assert (x != null);
if (size() < 2) return null;
if (this == x) return null;
SinglyLinkedListNode<E> prev = new SinglyLinkedListNode<>();
prev.next = this;
SinglyLinkedListNode<E> cur = this;
while (cur != x) {
prev = prev.next;
cur = cur.next;
}
return prev;
}
/**
* Return the last node.
* #return the last node.
*/
private SinglyLinkedListNode<E> last() {
if (size() == 0) return null;
if (size() == 1) return this;
SinglyLinkedListNode<E> prev = new SinglyLinkedListNode<>();
prev.next = this;
SinglyLinkedListNode<E> cur = this;
while (cur != null) {
prev = prev.next;
cur = cur.next;
}
return prev;
}
/**
* Unlinks non-null node x.
*/
E unlink(SinglyLinkedListNode<E> x) {
assert x != null;
final E element = x.value;
final SinglyLinkedListNode<E> next = x.next;
final SinglyLinkedListNode<E> prev = previous(x);
if (prev == null) {
this.value = next.value;
this.next = next.next;
} else {
prev.next = next;
}
x.next = null;
modCount++;
return element;
}
/**
* #inheritDoc
*/
public ListIterator<E> listIterator(int index) {
checkPositionIndex(index);
return new ListItr(index);
}
private class ListItr implements ListIterator<E> {
private SinglyLinkedListNode<E> lastReturned;
private SinglyLinkedListNode<E> next;
private int nextIndex;
private int expectedModCount = modCount;
ListItr(int index) {
assert isPositionIndex(index);
next = (index == size()) ? null : node(index);
nextIndex = index;
}
public boolean hasNext() {
return nextIndex < size();
}
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.value;
}
public boolean hasPrevious() {
return nextIndex > 0;
}
public E previous() {
throw new UnsupportedOperationException();
}
public int nextIndex() {
return nextIndex;
}
public int previousIndex() {
return nextIndex - 1;
}
public void remove() {
checkForComodification();
if (lastReturned == null)
throw new IllegalStateException();
unlink(lastReturned);
nextIndex--;
lastReturned = null;
expectedModCount++;
}
public void set(E e) {
if (lastReturned == null)
throw new IllegalStateException();
checkForComodification();
lastReturned.value = e;
}
public void add(E e) {
checkForComodification();
lastReturned = null;
if (next == null)
linkLast(e);
else
linkBefore(e, next);
nextIndex++;
expectedModCount++;
}
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (modCount == expectedModCount && nextIndex < size()) {
action.accept(next.value);
lastReturned = next;
next = next.next;
nextIndex++;
}
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
/**
* #inheritDoc
*/
public int size() {
int size = 0;
if (value == null) return size;
SinglyLinkedListNode<E> cur = this;
while (cur != null) {
size++;
cur = cur.next;
}
return size;
}
private void checkPositionIndex(int index) {
if (!isPositionIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* Returns the (non-null) Node at the specified element index.
*/
SinglyLinkedListNode<E> node(int index) {
assert isElementIndex(index);
SinglyLinkedListNode<E> x = this;
for (int i = 0; i < index; i++)
x = x.next;
return x;
}
/**
* Tells if the argument is the index of an existing element.
*/
private boolean isElementIndex(int index) {
return index >= 0 && index < size();
}
/**
* Tells if the argument is the index of a valid position for an
* iterator or an add operation.
*/
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size();
}
/**
* Constructs an IndexOutOfBoundsException detail message.
* Of the many possible refactorings of the error handling code,
* this "outlining" performs best with both server and client VMs.
*/
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: " + size();
}
}
Here is the unit test code:
#Test public void typeReferenceTest() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
final SinglyLinkedListNode<Integer> intList = objectMapper.readValue("[1,2,3,4,5]",
new TypeReference<SinglyLinkedListNode<Integer>>() {});
System.out.println(intList);
final ArrayList<SinglyLinkedListNode<Integer>> arrayOfList = objectMapper.readValue("[[1,2,3], [4,5,6]]",
new TypeReference<ArrayList<SinglyLinkedListNode<Integer>>>() {});
System.out.println(arrayOfList);
}
#Tatu Saloranta Thank you very much!
Here is my original blog, Deserialize a JSON Array to a Singly Linked List
From the previous question How to deserialize a JSON array to a singly linked list , I learned how to deserialize a JSON array to a singly linked list.
Now I want to deserialize a JSON object to a binary tree in Java.
The definition of the binary tree node is as the following:
public class BinaryTreeNode<E> {
public E value;
public BinaryTreeNode left;
public BinaryTreeNode right;
public BinaryTreeNode(final E value) {
this.value = value;
}
}
How to deserialize a JSON string such as:
{
"value": 2,
"left": {
"value": 1,
"left": null,
"right": null
},
"right": {
"value": 10,
"left": {
"value": 5,
"left": null,
"right": null
},
"right": null
}
}
to a binary tree?
2
/ \
1 10
/
5
Here is the unit test code:
#Test public void binaryTreeNodeTest() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
final ArrayList<Integer> intArray = objectMapper.readValue("[1,2,3,4,5]",
new TypeReference<ArrayList<Integer>>() {});
System.out.println(intArray);
/* How to achieve this?
2
/ \
1 10
/
5
{
"value": 2,
"left": {
"value": 1,
"left": null,
"right": null
},
"right": {
"value": 10,
"left": {
"value": 5,
"left": null,
"right": null
},
"right": null
}
}
*/
final String jsonStr = "{\n"
+ " \"value\": 2,\n"
+ " \"left\": {\n"
+ " \"value\": 1,\n"
+ " \"left\": null,\n"
+ " \"right\": null\n"
+ " },\n" + " \"right\": {\n"
+ " \"value\": 10,\n"
+ " \"left\": {\n"
+ " \"value\": 5,\n"
+ " \"left\": null,\n"
+ " \"right\": null\n"
+ " },\n"
+ " \"right\": null\n"
+ " }\n"
+ "}";
System.out.println(jsonStr);
final BinaryTreeNode<Integer> intTree = objectMapper.readValue(jsonStr,
new TypeReference<BinaryTreeNode<Integer>>() {});
System.out.println(intTree);
}
In other word, I want the BinaryTreeNode to be a first-class citizen the same as ArrayList, which can be used in all kinds of combinations, such as HashSet<BinaryTreeNode<Integer>>, BinaryTreeNode<HashMap<String, Integer>>, etc.
The solution is quite simple, since JSON can express tree naturally, Jackson can deal with recursive tree directly. Just annotate a constructor with JsonCreator:
public static class BinaryTreeNode<E>
{
public E value;
public BinaryTreeNode left;
public BinaryTreeNode right;
#JsonCreator
public BinaryTreeNode(#JsonProperty("value") final E value) {
this.value = value;
}
}
Let's write a unite test to try it:
package me.soulmachine.customized_collection;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class BinaryTreeNodeTest {
public static class BinaryTreeNode<E> {
public E value;
public BinaryTreeNode left;
public BinaryTreeNode right;
#JsonCreator
public BinaryTreeNode(#JsonProperty("value") final E value) {
this.value = value;
}
ArrayList<E> preOrder() {
final ArrayList<E> result = new ArrayList<>();
if (this.value == null) {
return result;
}
preOrder(this, result);
return result;
}
private static <E> void preOrder(BinaryTreeNode<E> root, ArrayList<E> result) {
if (root == null)
return;
result.add(root.value);
if (root.left != null)
preOrder(root.left, result);
if (root.right != null)
preOrder(root.right, result);
}
}
#Test public void binaryTreeNodeTest() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
/*
2
/ \
1 10
/
5
*/
final String jsonStr = "{\n"
+ " \"value\": 2,\n"
+ " \"left\": {\n"
+ " \"value\": 1,\n"
+ " \"left\": null,\n"
+ " \"right\": null\n"
+ " },\n" + " \"right\": {\n"
+ " \"value\": 10,\n"
+ " \"left\": {\n"
+ " \"value\": 5,\n"
+ " \"left\": null,\n"
+ " \"right\": null\n"
+ " },\n"
+ " \"right\": null\n"
+ " }\n"
+ "}";
System.out.println(jsonStr);
final BinaryTreeNode<Integer> intTree = objectMapper.readValue(jsonStr,
new TypeReference<BinaryTreeNode<Integer>>() {});
final List<Integer> listExpected = Arrays.asList(2, 1, 10, 5);
assertEquals(listExpected, intTree.preOrder());
}
}
A compact serialization format
Well, there is a little problem here, the JSON string above is very verbose. Let's use another kind of serialization format, i.e., serialize a binary tree in level order traversal. For example, the binary tree above can be serialized as the following JSON string:
[2,1,10,null,null,5]
Now how to deserialize this JSON string to a binary tree?
The idea is very similar to my previous article, Deserialize a JSON Array to a Singly Linked List. Just make the BinaryTreeNode implement java.util.list, pretend that it's a list, write our own deserialization code so that Jackson can treat a binary tree as a list.
The complete code of BinaryTreeNode is as the following:
package me.soulmachine.customized_collection;
import java.util.*;
public class BinaryTreeNode<E> extends AbstractSequentialList<E>
implements Cloneable, java.io.Serializable {
public E value;
public BinaryTreeNode<E> left;
public BinaryTreeNode<E> right;
/** has a left child, but it's a null node. */
private transient boolean leftIsNull;
/** has a right child, but it's a null node. */
private transient boolean rightIsNull;
/**
* Constructs an empty binary tree.
*/
public BinaryTreeNode() {
value = null;
left = null;
right = null;
}
/**
* Constructs an binary tree with one element.
*/
public BinaryTreeNode(final E value) {
if (value == null) throw new IllegalArgumentException("null value");
this.value = value;
left = null;
right = null;
}
/**
* Constructs a binary tree containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* #param c the collection whose elements are to be placed into this binary tree
* #throws NullPointerException if the specified collection is null
*/
public BinaryTreeNode(Collection<? extends E> c) {
this();
addAll(c);
}
/**
* #inheritDoc
*
* <p>Note: null in the middle counts, so that each father in the binary tree has a
* one-to-one mapping with the JSON array.</p>
*/
public int size() {
if (value == null) return 0;
Queue<BinaryTreeNode<E>> queue = new LinkedList<>();
queue.add(this);
int count = 0;
while (!queue.isEmpty()) {
final BinaryTreeNode<E> node = queue.remove();
++count;
if (node.left != null) {
queue.add(node.left);
} else {
if (node.leftIsNull) ++count;
}
if (node.right != null) {
queue.add(node.right);
} else {
if (node.rightIsNull) ++count;
}
}
return count;
}
/**
* Tells if the argument is the index of a valid position for an
* iterator or an add operation.
*/
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size();
}
/**
* Constructs an IndexOutOfBoundsException detail message.
* Of the many possible refactorings of the error handling code,
* this "outlining" performs best with both server and client VMs.
*/
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+ size();
}
private void checkPositionIndex(int index) {
if (!isPositionIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private class NodeAndFather {
private BinaryTreeNode<E> node;
private BinaryTreeNode<E> father;
private boolean isRight; // the father is the right child of the father
private NodeAndFather(BinaryTreeNode<E> node, BinaryTreeNode<E> father, boolean isRight) {
this.node = node;
this.father = father;
this.isRight = isRight;
}
}
/**
* Returns the (may be null) Node at the specified element index.
*/
NodeAndFather node(int index) {
checkPositionIndex(index);
if (value == null) return null;
Queue<NodeAndFather> queue = new LinkedList<>();
queue.add(new NodeAndFather(this, null, false));
for (int i = 0; !queue.isEmpty(); ++i) {
final NodeAndFather nodeAndFather = queue.remove();
if ( i == index) {
return nodeAndFather;
}
if (nodeAndFather.node != null) {
queue.add(new NodeAndFather(nodeAndFather.node.left, nodeAndFather.node, false));
queue.add(new NodeAndFather(nodeAndFather.node.right, nodeAndFather.node, true));
}
}
throw new IllegalArgumentException("Illegal index: " + index);
}
/**
* #inheritDoc
*/
public ListIterator<E> listIterator(int index) {
checkPositionIndex(index);
return new ListItr(index);
}
private class ListItr implements ListIterator<E> {
private NodeAndFather next;
private int nextIndex;
private int expectedModCount = modCount;
ListItr(int index) {
assert isPositionIndex(index);
next = node(index);
nextIndex = index;
}
public boolean hasNext() {
final BinaryTreeNode<E> cur = next.node;
return cur != null || (next.father.leftIsNull || next.father.rightIsNull);
}
//O(n)
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
final E result = next.node != null ? next.node.value : null;
next = node(nextIndex+1);
nextIndex++;
return result;
}
public boolean hasPrevious() {
throw new UnsupportedOperationException();
}
public E previous() {
throw new UnsupportedOperationException();
}
public int nextIndex() {
throw new UnsupportedOperationException();
}
public int previousIndex() {
throw new UnsupportedOperationException();
}
public void remove() {
throw new UnsupportedOperationException();
}
public void set(E e) {
throw new UnsupportedOperationException();
}
public void add(E e) { // always append at the tail
checkForComodification();
if (next == null) { // empty list
BinaryTreeNode.this.value = e;
BinaryTreeNode.this.left = null;
BinaryTreeNode.this.right = null;
} else {
final BinaryTreeNode<E> newNode = e != null ? new BinaryTreeNode<>(e) : null;
if (next.father == null) { // root
BinaryTreeNode<E> cur = next.node;
cur.left = newNode;
assert cur.right == null;
throw new UnsupportedOperationException();
} else {
if (next.isRight) {
if (next.father.right != null) throw new IllegalStateException();
next.father.right = newNode;
if (newNode == null) {
next.father.rightIsNull = true;
}
} else {
if (next.father.left != null) throw new IllegalStateException();
next.father.left = newNode;
if (newNode == null) {
next.father.leftIsNull = true;
}
}
}
}
modCount++;
expectedModCount++;
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
// the following functions are just for unit tests.
ArrayList<E> preOrder() {
final ArrayList<E> result = new ArrayList<>();
if (this.value == null) {
return result;
}
preOrder(this, result);
return result;
}
private static <E> void preOrder(BinaryTreeNode<E> root, ArrayList<E> result) {
if (root == null)
return;
result.add(root.value);
if (root.left != null)
preOrder(root.left, result);
if (root.right != null)
preOrder(root.right, result);
}
ArrayList<E> inOrder() {
final ArrayList<E> result = new ArrayList<>();
if (this.value == null) {
return result;
}
inOrder(this, result);
return result;
}
private static <E> void inOrder(BinaryTreeNode<E> root, ArrayList<E> result) {
if (root == null)
return;
if (root.left != null)
inOrder(root.left, result);
result.add(root.value);
if (root.right != null)
inOrder(root.right, result);
}
ArrayList<E> postOrder() {
final ArrayList<E> result = new ArrayList<>();
if (this.value == null) {
return result;
}
postOrder(this, result);
return result;
}
private static <E> void postOrder(BinaryTreeNode<E> root, ArrayList<E> result) {
if (root == null)
return;
if (root.left != null)
postOrder(root.left, result);
if (root.right != null)
postOrder(root.right, result);
result.add(root.value);
}
ArrayList<E> levelOrder() {
final ArrayList<E> result = new ArrayList<>();
if (this.value == null) {
return result;
}
Queue<BinaryTreeNode<E>> queue = new LinkedList<>();
queue.add(this);
while (!queue.isEmpty()) {
final BinaryTreeNode<E> node = queue.remove();
result.add(node.value);
if (node.left != null)
queue.add(node.left);
if (node.right != null)
queue.add(node.right);
}
return result;
}
}
Then comes with the unit tests:
java
package me.soulmachine.customized_collection;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class BinaryTreeNodeTest
{
#Test public void deserializeTest() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
final List<Integer> intList = Arrays.asList(2,1,10,null,null,5);
/*
2
/ \
1 10
/
5
*/
// TODO: the time complexity is O(n^2)
final BinaryTreeNode<Integer> intTree = objectMapper.readValue("[2,1,10,null,null,5]",
new TypeReference<BinaryTreeNode<Integer>>() {});
assertEquals(intList, intTree);
assertEquals(Arrays.asList(2, 1, 10, 5), intTree.levelOrder());
assertEquals(Arrays.asList(2, 1, 10, 5), intTree.preOrder());
assertEquals(Arrays.asList(1, 2, 5, 10), intTree.inOrder());
assertEquals(Arrays.asList(1, 5, 10, 2), intTree.postOrder());
}
}
This article is inspired by Tatu Saloranta from this post, special thanks to him!
Here is my original blog, Deserialize a JSON String to a Binary Tree
My main class code
{
ArrayList<Item> items = new ArrayList<Item>();
Scanner file = new Scanner(kk.class.getResourceAsStream("product.txt"));
while (file.hasNextLine()) {
String[] sp = file.nextLine().split(",");
// extract item number, description, price and type
itemNum = Integer.parseInt(sp[0]);
des = sp[1];
price = Integer.parseInt(sp[2]);
Item objt = new Item(itemNum, des, price); // Creating a new object
items.add(objt); // Adding it to the list
}
System.out.println(items);
}
output I am getting
[dada.Item#4a5d4a62, dada.Item#32be8e12, dada.Item#7c6159c4, dada.Item#5b4c92a7, dada.Item#3040c5,
My item class code
private int itemNum = 0;
private String des = "";
private int price = 0;
public Item(int i, String d, int p) {
itemNum = i;
des = d;
price = p;
}
You're printing the Item reference's address instead of the fields inside your Item object. You have print the fields inside each Item object by looping through them.
Replace this line
System.out.println(items);
with
for(Item i : items)
{
System.out.println(i.getItemNum()+" "+i.getDes()+" "+i.getPrice());
}
Change the class so that you could access your private fields
private int itemNum = 0;
private String des = "";
private int price = 0;
public Item(int i, String d, int p) {
itemNum = i;
des = d;
price = p;
}
public void setItemNum(int itemNum) {
this.itemNum = itemNum;
}
public int getItemNum() {
return itemNum;
}
public void setDes(String des) {
this.des = des;
}
public String getDes() {
return des;
}
public void setPrice(int price) {
this.price = price;
}
public int getPrice() {
return price;
}
I am using the jsmpp lib for sending sms. The SMSC center returns negative response like 61,62 which are Invalid scheduled delivery time and Invalid Validty Period value. After talking with SMSC support, they require to set a default timeout for the message to be delivered, after some search on jsmpp site, didn't find it. Thanks for any suggestions ?
According to SMPP standard it should be possible to leave both of these null, but if Validity Period is required, this can be either an absolute date or a relative one.
The format should be YYMMDDhhmmsstnnp, where
YY is a two digit year (00-99)
MM is month (01-12)
DD is day (01-31)
hh is hours (00-23)
mm is minutes (00-59)
ss is seconds (00-59)
t is tenths of second (00-59)
nn is the time difference in quarter hours between local time and UTC (00-48)
p can be one of the following :-
'+' local time is ahead of UTC.
'-' local time is behind UTC.
'R' This is a relative time.
So to make the validity period 1 hour using a relative time use the following: "000000010000000R"
In my project I didn't have business requirement to schedule delivery time and set validity Period, so I set them null and it's work fine :-)
I use this class to load smpp config from properties file. Code that will using it will looks more readable and simple :-)
SMPPConfigManager is an interface for this class. It's possible to read this config not only from properties file. For example from Db and you can then implement this interface in new class.
package ru.rodin.denis.smpp;
import java.util.Properties;
import org.jsmpp.bean.*;
/**
*
* #author Denis Rodin
*/
public class SMPPFileConfig implements SMPPConfigManager {
private String host;
private int port;
private String systemId;
private String password;
private String systemType;
private TypeOfNumber sourceAddrTon;
private TypeOfNumber destAddrTon;
private NumberingPlanIndicator sourceAddrNpi;
private NumberingPlanIndicator destAddrNpi;
private String addressRange;
private int connectTimeout;
private long reconnectInterval;
private String sourceAddr;
private String destinationAddr;
private SMSCDeliveryReceipt deliveryReceipt;
private RegisteredDelivery registeredDelivery;
private BindType bindType;
private ESMClass esmClass;
private byte protocolId;
private byte priorityFlag;
private String scheduleDeliveryTime;
private String validityPeriod;
private byte replaceIfPresentFlag;
private GeneralDataCoding generalDataCoding;
private boolean generalDataCoding_compressed = true;
private boolean generalDataCoding_containMessageClass = true;
private MessageClass generalDataCoding_messageClass = MessageClass.CLASS1;
private Alphabet generalDataCoding_alphabet = Alphabet.ALPHA_DEFAULT;
private byte smDefaultMsgId;
private long transactionTimer;
private int enquireLinkTimer;
public SMPPFileConfig(Properties prop) {
this.host = prop.getProperty("smpp.host");
this.port = Integer.parseInt(prop.getProperty("smpp.port"));
this.systemId = prop.getProperty("smpp.systemId");
this.password = prop.getProperty("smpp.password");
this.systemType = prop.getProperty("smpp.systemType");
this.sourceAddrTon = getTypeOfNumber(SMPPConfigManager.AddrTon.SOURCE, prop);
this.destAddrTon = getTypeOfNumber(SMPPConfigManager.AddrTon.DEST, prop);
this.sourceAddrNpi = getNumberingPlanIndicator(SMPPConfigManager.AddrNpi.SOURCE, prop);
this.destAddrNpi = getNumberingPlanIndicator(SMPPConfigManager.AddrNpi.DEST, prop);
this.addressRange = prop.getProperty("smpp.addressRange");
this.connectTimeout = Integer.parseInt(prop.getProperty("smpp.connect.timeout"));
this.reconnectInterval = Long.parseLong(prop.getProperty("smpp.reconnect.interval"));
this.sourceAddr = prop.getProperty("smpp.sourceAddr");
this.destinationAddr = null;
this.deliveryReceipt = getSMSCDeliveryReceipt(prop.getProperty("smpp.SMSC.delivery.receipt"));
this.registeredDelivery = new RegisteredDelivery(deliveryReceipt);
this.bindType = getBindTypeFromProp(prop.getProperty("smpp.bindType"));
this.esmClass = createESMClass(prop.getProperty("smpp.ESMClass.MessageMode"), prop.getProperty("smpp.ESMClass.MessageType"), prop.getProperty("smpp.ESMClass.GSMSpecificFeature"));
this.protocolId = new Byte(prop.getProperty("smpp.protocolId"));
this.priorityFlag = new Byte(prop.getProperty("smpp.priorityFlag"));
this.scheduleDeliveryTime = prop.getProperty("smpp.scheduleDeliveryTime");
this.validityPeriod = prop.getProperty("smpp.validityPeriod");
this.replaceIfPresentFlag = new Byte(prop.getProperty("smpp.replaceIfPresentFlag"));
this.generalDataCoding = new GeneralDataCoding(generalDataCoding_compressed, generalDataCoding_containMessageClass, generalDataCoding_messageClass, generalDataCoding_alphabet);
this.smDefaultMsgId = new Byte(prop.getProperty("smpp.smDefaultMsgId"));
this.transactionTimer = Long.parseLong(prop.getProperty("smpp.transactionTimer"));
this.enquireLinkTimer = Integer.parseInt(prop.getProperty("smpp.enquireLinkTimer"));
}
#Override
public String toString() {
return "SMPPFileConfig{" + "host=" + host + ", port=" + port + ", systemId=" + systemId + ", password=" + password + ", systemType=" + systemType + ", sourceAddrTon=" + sourceAddrTon + ", destAddrTon=" + destAddrTon + ", sourceAddrNpi=" + sourceAddrNpi + ", destAddrNpi=" + destAddrNpi + ", addressRange=" + addressRange + ", connectTimeout=" + connectTimeout + ", reconnectInterval=" + reconnectInterval + ", sourceAddr=" + sourceAddr + ", destinationAddr=" + destinationAddr + ", deliveryReceipt=" + deliveryReceipt + ", registeredDelivery=" + registeredDelivery + ", bindType=" + bindType + ", esmClass=" + esmClass + ", protocolId=" + protocolId + ", priorityFlag=" + priorityFlag + ", scheduleDeliveryTime=" + scheduleDeliveryTime + ", validityPeriod=" + validityPeriod + ", replaceIfPresentFlag=" + replaceIfPresentFlag + ", generalDataCoding=" + generalDataCoding + ", generalDataCoding_compressed=" + generalDataCoding_compressed + ", generalDataCoding_containMessageClass=" + generalDataCoding_containMessageClass + ", generalDataCoding_messageClass=" + generalDataCoding_messageClass + ", generalDataCoding_alphabet=" + generalDataCoding_alphabet + ", smDefaultMsgId=" + smDefaultMsgId + '}';
}
#Override
public String getAddressRange() {
return addressRange;
}
#Override
public int getConnectTimeout() {
return connectTimeout;
}
#Override
public SMSCDeliveryReceipt getDeliveryReceipt() {
return deliveryReceipt;
}
#Override
public RegisteredDelivery getRegisteredDelivery() {
return registeredDelivery;
}
#Override
public NumberingPlanIndicator getDestAddrNpi() {
return destAddrNpi;
}
#Override
public TypeOfNumber getDestAddrTon() {
return destAddrTon;
}
#Override
public void setDestinationAddr(String destinationAddr) {
this.destinationAddr = destinationAddr;
}
#Override
public String getDestinationAddr() {
return destinationAddr;
}
#Override
public String getHost() {
return host;
}
#Override
public String getPassword() {
return password;
}
#Override
public int getPort() {
return port;
}
#Override
public long getReconnectInterval() {
return reconnectInterval;
}
#Override
public String getSourceAddr() {
return sourceAddr;
}
#Override
public NumberingPlanIndicator getSourceAddrNpi() {
return sourceAddrNpi;
}
#Override
public TypeOfNumber getSourceAddrTon() {
return sourceAddrTon;
}
#Override
public String getSystemId() {
return systemId;
}
#Override
public String getSystemType() {
return systemType;
}
#Override
public BindType getBindType() {
return bindType;
}
#Override
public ESMClass getESMClass() {
return esmClass;
}
#Override
public void setESMClass(ESMClass esmClass) {
this.esmClass = esmClass;
}
#Override
public byte getProtocolId() {
return protocolId;
}
#Override
public byte getPriorityFlag() {
return priorityFlag;
}
#Override
public String getScheduleDeliveryTime() {
return scheduleDeliveryTime;
}
#Override
public String getValidityPeriod() {
return validityPeriod;
}
#Override
public byte getReplaceIfPresentFlag() {
return replaceIfPresentFlag;
}
#Override
public GeneralDataCoding getGeneralDataCoding() {
return generalDataCoding;
}
#Override
public byte getsmDefaultMsgId(){
return smDefaultMsgId;
}
#Override
public long getTransactionTimer()
{
return transactionTimer;
}
#Override
public int getEnquireLinkTimer()
{
return enquireLinkTimer;
}
private ESMClass createESMClass(String messageMode, String messageType, String GSMSpecificFeature) {
return new ESMClass(getESMClassMessageMode(messageMode), getESMMessageType(messageType), getESMGSMSpecificFeature(GSMSpecificFeature));
}
private MessageMode getESMClassMessageMode(String type) {
if (type.equals("DEFAULT")) {
return MessageMode.DEFAULT;
} else if (type.equals("DATAGRAM")) {
return MessageMode.DATAGRAM;
} else if (type.equals("STORE_AND_FORWARD")) {
return MessageMode.STORE_AND_FORWARD;
} else if (type.equals("TRANSACTION")) {
return MessageMode.TRANSACTION;
} else {
return null;
}
}
private MessageType getESMMessageType(String type) {
if (type.equals("DEFAULT")) {
return MessageType.DEFAULT;
} else if (type.equals("CONV_ABORT")) {
return MessageType.CONV_ABORT;
} else if (type.equals("ESME_DEL_ACK")) {
return MessageType.ESME_DEL_ACK;
} else if (type.equals("ESME_MAN_ACK")) {
return MessageType.ESME_MAN_ACK;
} else if (type.equals("INTER_DEL_NOTIF")) {
return MessageType.INTER_DEL_NOTIF;
} else if (type.equals("SME_DEL_ACK")) {
return MessageType.SME_DEL_ACK;
} else if (type.equals("SME_MAN_ACK")) {
return MessageType.SME_MAN_ACK;
} else if (type.equals("SMSC_DEL_RECEIPT")) {
return MessageType.SMSC_DEL_RECEIPT;
} else {
return null;
}
}
private GSMSpecificFeature getESMGSMSpecificFeature(String type) {
if (type.equals("DEFAULT")) {
return GSMSpecificFeature.DEFAULT;
} else if (type.equals("REPLYPATH")) {
return GSMSpecificFeature.REPLYPATH;
} else if (type.equals("UDHI")) {
return GSMSpecificFeature.UDHI;
} else if (type.equals("UDHI_REPLYPATH")) {
return GSMSpecificFeature.UDHI_REPLYPATH;
} else {
return null;
}
}
private BindType getBindTypeFromProp(String type) {
//String type = prop.getProperty("smpp.bindType");
if (type.equals("BIND_RX")) {
return BindType.BIND_RX;
} else if (type.equals("BIND_TX")) {
return BindType.BIND_TX;
} else if (type.equals("BIND_TRX")) {
return BindType.BIND_TRX;
} else {
return null;
}
}
private TypeOfNumber getTypeOfNumber(SMPPConfigManager.AddrTon ton, Properties prop) {
String type;
if (ton == SMPPConfigManager.AddrTon.SOURCE) {
type = prop.getProperty("smpp.sourceAddrTon");
} else {
type = prop.getProperty("smpp.destAddrTon");
}
if (type.equals("ABBREVIATED")) {
return TypeOfNumber.ABBREVIATED;
} else if (type.equals("ALPHANUMERIC")) {
return TypeOfNumber.ALPHANUMERIC;
} else if (type.equals("INTERNATIONAL")) {
return TypeOfNumber.INTERNATIONAL;
} else if (type.equals("NATIONAL")) {
return TypeOfNumber.NATIONAL;
} else if (type.equals("NETWORK_SPECIFIC")) {
return TypeOfNumber.NETWORK_SPECIFIC;
} else if (type.equals("SUBSCRIBER_NUMBER")) {
return TypeOfNumber.SUBSCRIBER_NUMBER;
} else if (type.equals("UNKNOWN")) {
return TypeOfNumber.UNKNOWN;
} else {
return null;
}
}
private SMSCDeliveryReceipt getSMSCDeliveryReceipt(String type) {
//String type = prop.getProperty("smpp.SMSC.delivery.receipt");
if (type.equals("DEFAULT")) {
return SMSCDeliveryReceipt.DEFAULT;
} else if (type.equals("SUCCESS")) {
return SMSCDeliveryReceipt.SUCCESS;
} else if (type.equals("SUCCESS_FAILURE")) {
return SMSCDeliveryReceipt.SUCCESS_FAILURE;
} else {
return null;
}
}
private NumberingPlanIndicator getNumberingPlanIndicator(SMPPConfigManager.AddrNpi npi, Properties prop) {
String type;
if (npi == SMPPConfigManager.AddrNpi.SOURCE) {
type = prop.getProperty("smpp.sourceAddrNpi");
} else {
type = prop.getProperty("smpp.destAddrNpi");
}
if (type.equals("DATA")) {
return NumberingPlanIndicator.DATA;
} else if (type.equals("ERMES")) {
return NumberingPlanIndicator.ERMES;
} else if (type.equals("INTERNET")) {
return NumberingPlanIndicator.INTERNET;
} else if (type.equals("ISDN")) {
return NumberingPlanIndicator.ISDN;
} else if (type.equals("LAND_MOBILE")) {
return NumberingPlanIndicator.LAND_MOBILE;
} else if (type.equals("NATIONAL")) {
return NumberingPlanIndicator.NATIONAL;
} else if (type.equals("PRIVATE")) {
return NumberingPlanIndicator.PRIVATE;
} else if (type.equals("TELEX")) {
return NumberingPlanIndicator.TELEX;
} else if (type.equals("WAP")) {
return NumberingPlanIndicator.WAP;
} else if (type.equals("UNKNOWN")) {
return NumberingPlanIndicator.UNKNOWN;
} else {
return null;
}
}
}
when you submit current time as scheduled delivery time this error may occur.because it takes some time to send request. so the time you mentioned might be in past .so set the scheduled delivery time to (current time + 10 seconds )
long TEN_SECONDS=10000;//millisecs
Calendar date = Calendar.getInstance();
long t= date.getTimeInMillis();
Date scheduleDeliveryTime=new Date(t + ( TEN_SECONDS));