I have below table
question_text_id question_id language_id question_text
2 7 1 english_text_1
3 7 2 spanish_text_1
4 8 2 spanish_text_2
5 8 1 english_text_2
NOw i want to create list for each distinct question_id
i have used below code
List<QuestionText> questionTextList = questionManager.getQuestionsTextByQuestionId(Long.parseLong(questions.getQuestionId().toString()));
for (QuestionText questionText : questionTextList) {
questionMap.put("questionId", questionText.getQuestionId());
questionMap.put("language", questionText.getLanguageId());
if(questionText.getLanguageId().longValue() == 1){
questionMap.put("englishQuestionText",questionText.getQuestionText());
} else {
questionMap.put("spanishQuestionText",questionText.getQuestionText());
}
questionListMap.add(questionMap);
}
adminCollectionBookendModel.put("questionListMap",questionListMap);
[{questionId = 1,language=1, englishQuestionText = english_text_1,spanishQuestionText=spanish_text_1},{questionId = 1,language=2, englishQuestionText = english_text_1,spanishQuestionText=spanish_text_1}]
But this give me repeatetion of object of same data if i have both spanish and english question text as shown above. How to get unique list?
How to get both spanish text and english text for each question_id along with language_id and to access it?
Please help me on this
The first step would be to create a POJO Class like this,
public class QuestionDetails {
private int questionId;
private int englishLanguageId;
private int spanishLanguageId;
private String englishLanguageText;
private String spanishLanguageText;
public int getQuestionId() {
return questionId;
}
public void setQuestionId(int questionId) {
this.questionId = questionId;
}
public int getEnglishLanguageId() {
return englishLanguageId;
}
public void setEnglishLanguageId(int englishLanguageId) {
this.englishLanguageId = englishLanguageId;
}
public int getSpanishLanguageId() {
return spanishLanguageId;
}
public void setSpanishLanguageId(int spanishLanguageId) {
this.spanishLanguageId = spanishLanguageId;
}
public String getEnglishLanguageText() {
return englishLanguageText;
}
public void setEnglishLanguageText(String englishLanguageText) {
this.englishLanguageText = englishLanguageText;
}
public String getSpanishLanguageText() {
return spanishLanguageText;
}
public void setSpanishLanguageText(String spanishLanguageText) {
this.spanishLanguageText = spanishLanguageText;
}
#Override
public String toString() {
return new StringBuilder().append("questionId: ").append(questionId)
.append(" ,englishLanguageId: ").append(englishLanguageId)
.append(" ,englishLanguageText: ").append(englishLanguageText)
.append(" ,spanishLanguageId: ").append(spanishLanguageId)
.append(" ,spanishLanguageText: ").append(spanishLanguageText)
.toString();
}
}
Next step would be to change your code snippet like this:
List<QuestionDetails> questionsList = new ArrayList<>();
List<QuestionText> questionTextList = questionManager
.getQuestionsTextByQuestionId(Long.parseLong(questions
.getQuestionId().toString()));
for (QuestionText questionText : questionTextList) {
/* Get QuestionDetails Object */
QuestionDetails qd = getQuestionDetails(
questionText.getQuestionId(), questionsList);
/* Check Null */
if(null == qd) {
/* Get New Object */
qd = new QuestionDetails();
/* Add Object To List */
questionsList.add(qd);
}
/* Set Question ID */
qd.setQuestionId(questionText.getQuestionId());
/* Set Language ID & Text */
if (questionText.getLanguageId().longValue() == 1) {
qd.setEnglishLanguageId(questionText.getLanguageId()
.longValue());
qd.setEnglishLanguageText(questionText.getQuestionText());
} else {
qd.setSpanishLanguageId(questionText.getLanguageId()
.longValue());
qd.setSpanishLanguageText(questionText.getQuestionText());
}
}
adminCollectionBookendModel.put("questionListMap", questionsList);
Finally, here is the implementation of the getQuestionDetails function:
private QuestionDetails getQuestionDetails(int questionId,
List<QuestionDetails> questionsList) {
/* Search Existing Object */
for (QuestionDetails qd : questionsList) {
/* Match Found */
if (qd.getQuestionId() == questionId) {
return qd;
}
}
/* No Object Found */
return null;
}
I would recommend doing the following:
To distinguish QuestionText, you need to override equals method using question_text_id. Otherwise two questions with the same question_id, but different language texts would be equal.
Then create two separate maps for each language. Then just iterate throug all questions and put each question in a corresponding map by question_id. You can retrive a question object by its question_id and get all necessary fields from it, including spanish / english text
List<QuestionText> questionTextList = questionManager.getQuestionsTextByQuestionId(Long.parseLong(questions.getQuestionTextId().toString()));
for (QuestionText questionText : questionTextList) {
if(questionText.getLanguageId().longValue() == 1){
englishQuestionMap.put("question_id",questionText);
} else {
spanishQuestionMap.put("question_id",questionText);
}
questionListMap.add(questionMap);
}
So, your maps will have type of Map<Long, QuestionText>
Related
For a project, which generates XML-files based on a XSD-file, I want to automatically generate the documentation. *
In this documentation I list the different elements defined in the XSD.
And for each element I want to show an example of that element.
The problem is, that the XML-example might be quite long and contains a lot of children.
Therefore I want to shorten the example by:
limiting the shown depth
limiting the amount of elements in a list
For the root-element that example might look like the following:
<root>
<elements>
<element>...<element>
<element>...<element>
<element>...<element>
...
</elements>
</root>
My approach:
To generate classes from the XSD and to generate and validate the XML files I use JAXB.
But I could not figure out how to marshal a Non-Root element.
Therefore I am generating my examples with XStream.
To limit the XML-example I am trying to decorate the PrettyPrintWriter, but that seems to be quite cumbersome.
The two decorators can be seen in my answer.
I just did not expect to care about the internals of a library for such a (common?) feature.
Is there an easier way to do this? (I can also use another library than XStream, or none at all.)
*
My approach is influenced by Spring Auto Rest Docs
To limit the shown depth I created the following XStream WriterWrapper. The class can wrap for example a PrettyPrintWriter and ensures that the wrapped writer only receives the nodes above a given depth threshold.
public class RestrictedPrettyPrintWriter extends WriterWrapper {
private final ConverterLookup converterLookup;
private final int maximalDepth;
private int depth;
public RestrictedPrettyPrintWriter(HierarchicalStreamWriter sw, ConverterLookup converterLookup, int maximalDepth) {
super(sw);
this.converterLookup = converterLookup;
this.maximalDepth = maximalDepth;
}
#Override public void startNode(String name, Class clazz) {
Converter converter = this.converterLookup.lookupConverterForType(clazz);
boolean isSimpleType = converter instanceof SingleValueConverter;
_startNode(name, !isSimpleType);
}
#Override public void startNode(String name) {
_startNode(name, false);
}
#Override public void endNode() {
if (_isLessDeepThanMaximalDepth() || _isMaximalDepthReached()) {
super.endNode();
}
depth--;
}
#Override public void addAttribute(String key, String value) {
if (_isLessDeepThanMaximalDepth() || _isMaximalDepthReached()) {
super.addAttribute(key, value);
}
}
#Override public void setValue(String text) {
if (_isLessDeepThanMaximalDepth() || _isMaximalDepthReached()) {
super.setValue(text);
}
}
/**
* #param name name of the new node
* #param isComplexType indicates if the element is complex or contains a single value
*/
private void _startNode(String name, boolean isComplexType) {
depth++;
if (_isLessDeepThanMaximalDepth()) {
super.startNode(name);
} else if (_isMaximalDepthReached()) {
super.startNode(name);
/*
* set the placeholder value now
* setValue() will never be called for complex types
*/
if (isComplexType) {
super.setValue("...");
}
}
}
private boolean _isMaximalDepthReached() {
return depth == maximalDepth;
}
private boolean _isLessDeepThanMaximalDepth() {
return depth < maximalDepth;
}
}
To limit the lists, I tried, in a first attempt, to modify the XStream CollectionConverter. But this approach was not general enough because implicit lists do not use this converter.
Therefore I created another WriterWrapper which counts the consecutive occurrences of elements with the same name.
public class RestrictedCollectionWriter extends WriterWrapper {
private final int maxConsecutiveOccurences;
private int depth;
/** Contains one element per depth.
* More precisely: the current element and its parents.
*/
private Map < Integer, Elements > elements = new HashMap < > ();
public RestrictedCollectionWriter(HierarchicalStreamWriter sw, int maxConsecutiveOccurences) {
super(sw);
this.maxConsecutiveOccurences = maxConsecutiveOccurences;
}
#Override public void startNode(String name, Class clazz) {
_startNode(name);
}
#Override public void startNode(String name) {
_startNode(name);
}
#Override public void endNode() {
if (_isCurrentElementPrintable()) {
super.endNode();
}
depth--;
}
#Override public void addAttribute(String key, String value) {
if (_isCurrentElementPrintable()) {
super.addAttribute(key, value);
}
}
#Override public void setValue(String text) {
if (_isCurrentElementPrintable()) {
super.setValue(text);
}
}
/**
* #param name name of the new node
*/
private void _startNode(String name) {
depth++;
Elements currentElement = this.elements.getOrDefault(depth, new Elements());
this.elements.put(depth, currentElement);
Elements parent = this.elements.get(depth - 1);
boolean parentPrintable = parent == null ? true : parent.isPrintable();
currentElement.setName(name, parentPrintable);
if (currentElement.isPrintable()) {
super.startNode(name);
}
}
private boolean _isCurrentElementPrintable() {
Elements currentElement = this.elements.get(depth);
return currentElement.isPrintable();
}
/**
* Evaluates if an element is printable or not.
* This is based on the concurrent occurences of the element's name
* and if the parent element is printable or not.
*/
private class Elements {
private String name = "";
private int concurrentOccurences = 0;
private boolean parentPrintable;
public void setName(String name, boolean parentPrintable) {
if (this.name.equals(name)) {
concurrentOccurences++;
} else {
concurrentOccurences = 1;
}
this.name = name;
this.parentPrintable = parentPrintable;
}
public boolean isPrintable() {
return parentPrintable && concurrentOccurences <= maxConsecutiveOccurences;
}
}
}
The following listing shows, how the two classes can be used.
XStream xstream = new XStream(new StaxDriver());
StringWriter sw = new StringWriter();
PrettyPrintWriter pw = new PrettyPrintWriter(sw);
RestrictedCollectionWriter cw = new RestrictedCollectionWriter(pw, 3);
xstream.marshal(objectToMarshal, new RestrictedPrettyPrintWriter(cw, xstream.getConverterLookup(), 3));
I have two classes as shown below. I need to use these two classes to extract few things.
public final class ProcessMetadata {
private final String clientId;
private final String deviceId;
// .. lot of other fields here
// getters here
}
public final class ProcMetadata {
private final String deviceId;
private final Schema schema;
// .. lot of other fields here
}
Now I have below code where I am iterating above two classes and extracting schema given a clientId.
public Optional<Schema> getSchema(final String clientId) {
for (ProcessMetadata metadata1 : processMetadataList) {
if (metadata1.getClientId().equalsIgnoreCase(clientId)) {
String deviceId = metadata1.getDeviceId();
for (ProcMetadata metadata2 : procMetadataList) {
if (metadata2.getDeviceId().equalsIgnoreCase(deviceId)) {
return Optional.of(metadata2.getSchema());
}
}
}
}
return Optional.absent();
}
Is there any better way of getting what I need by iterating those two above classes in couple of lines instead of what I have? I am using Java 7.
You're doing a quadratic* search operation, which is inneficient. You can do this operation in constant time by first creating (in linear time) a mapping from id->object for each list. This would look something like this:
// do this once, in the constructor or wherever you create these lists
// even better discard the lists and use the mappings everywhere
Map<String, ProcessMetadata> processMetadataByClientId = new HashMap<>();
for (ProcessMetadata process : processMetadataList) {
processMetadataByClientId.put(process.getClientId(), process);
}
Map<String, ProcMetadata> procMetadataByDeviceId = new HashMap<>();
for (ProcMetadata metadata2 : procMetadataList) {
procMetadataByDeviceId.put(proc.getDeviceId(), proc);
}
Then your lookup simply becomes:
public Optional<Schema> getSchema(String clientId) {
ProcessMetadata process = processMetadataByClientId.get(clientId);
if (process != null) {
ProcMetadata proc = procMetadataByDeviceId.get(process.getDeviceId());
if (proc != null) {
return Optional.of(proc.getSchema());
}
}
return Optional.absent();
}
In Java 8 you could write it like this:
public Optional<Schema> getSchema(String clientId) {
return Optional.fromNullable(processMetadataByClientId.get(clientId))
.map(p -> procMetadataByDeviceId.get(p.getDeviceId()))
.map(p -> p.getSchema());
}
* In practice your algorithm is linear assuming client IDs are unique, but it's still technically O(n^2) because you potentially touch every element of the proc list for every element of the process list. A slight tweak to your algorithm can guarentee linear time (again assuming unique IDs):
public Optional<Schema> getSchema(final String clientId) {
for (ProcessMetadata metadata1 : processMetadataList) {
if (metadata1.getClientId().equalsIgnoreCase(clientId)) {
String deviceId = metadata1.getDeviceId();
for (ProcMetadata metadata2 : procMetadataList) {
if (metadata2.getDeviceId().equalsIgnoreCase(deviceId)) {
return Optional.of(metadata2.getSchema());
}
}
// adding a break here ensures the search doesn't become quadratic
break;
}
}
return Optional.absent();
}
Though of course using maps ensures constant-time, which is far better.
I wondered what could be done with Guava, and accidentally wrote this hot mess.
import static com.google.common.collect.Iterables.tryFind
public Optional<Schema> getSchema(final String clientId) {
Optional<String> deviceId = findDeviceIdByClientId(clientId);
return deviceId.isPresent() ? findSchemaByDeviceId(deviceId.get()) : Optional.absent();
}
public Optional<String> findDeviceIdByClientId(String clientId) {
return tryFind(processMetadataList, new ClientIdPredicate(clientId))
.transform(new Function<ProcessMetadata, String>() {
String apply(ProcessMetadata processMetadata) {
return processMetadata.getDeviceId();
}
});
}
public Optional<Schema> findSchemaByDeviceId(String deviceId) {
return tryFind(procMetadataList, new DeviceIdPredicate(deviceId.get())
.transform(new Function<ProcMetadata, Schema>() {
Schema apply(ProcMetadata procMetadata) {
return processMetadata.getSchema();
}
});
}
class DeviceIdPredicate implements Predicate<ProcMetadata> {
private String deviceId;
public DeviceIdPredicate(String deviceId) {
this.deviceId = deviceId;
}
#Override
public boolean apply(ProcMetadata metadata2) {
return metadata2.getDeviceId().equalsIgnoreCase(deviceId)
}
}
class ClientIdPredicate implements Predicate<ProcessMetadata> {
private String clientId;
public ClientIdPredicate(String clientId) {
this.clientId = clientId;
}
#Override
public boolean apply(ProcessMetadata metadata1) {
return metadata1.getClientId().equalsIgnoreCase(clientId);
}
}
Sorry.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 6 years ago.
I have a snippet of code (below) that when run, will (ideally) fill an app array to look something like this:
Header 1:
App 1
App 2
Header 2:
App 3
App 4
etc.
However, when I run it in my emulator, it produces this:
Header 1:
App 1
App 2
App 3
App 4
...
Header 2:
App 1
...
I'm not sure why this happens, as I have looked up the defaults and everywhere I look, people say that Java defaults to passing by value, not by reference. If this is true, how come it adds every app to every category?
Preconditions:
Store is defined as a list of class "App", each element containing a header and title, among other things.
ListDataChild is an empty hashmap, with types > to be filled by the loop and then outputted via an expandable list view. I would post the code for the view, but it is very bulky and long so I'll just add a simple testing algorithm at the end.
EmptyList is just that, a list of type that has nothing inside (at least to begin with? Could it be changing?)
Code:
listDataChild = new HashMap<String, List<App>>();
List<App> emptylist = new ArrayList<>();
List<App> Store = synced.getAppStore();
Boolean juststarted = true;
for (App el : Store)
{
if (juststarted)
{
juststarted = false;
listDataChild.put(el.getHeader(), emptylist);
listDataChild.get(el.getHeader()).add(el);
} else {
if (listDataChild.containsKey(el.getHeader())) {
listDataChild.get(el.getHeader()).add(el);
} else {
listDataChild.put(el.getHeader(), emptylist);
listDataChild.get(el.getHeader()).add(el);
}
}
}
//TESTING
for (String header : listDataChild.keySet())
{
for (int j = 0; j < listDataChild.get(header).size(); j++)
{
System.out.println("HashMap at " + header + ", " + j + ": " + listDataChild.get(header).get(j).getTitle());
}
}
App.Java:
public class App {
public String header,title,link,url,redirect,icon;
public Double order;
public Boolean selected;
public App() {
header = "";
title = "";
link = "";
url = "";
redirect = "";
icon = "";
order = 0.0;
selected = false;
}
public int compareTo(App another) {
if (this.getOrder()<another.getOrder()){
return -1;
}else{
return 1;
}
}
public void setHeader(String h) {
header = h;
return;
}
public void setTitle(String t) {
title = t;
return;
}
public void setLink(String l) {
link = l;
return;
}
public void setUrl(String u) {
url = u;
return;
}
public void setRedirect(String r) {
redirect = r;
return;
}
public void setIcon(String i) {
icon = i;
return;
}
public void setOrder(Double o) {
order = o;
return;
}
public void setSelected(Boolean s) {
selected = s;
return;
}
public String getTitle()
{
return title;
}
public String getHeader()
{
return header;
}
public Double getOrder()
{
return order;
}
}
Thanks in advance!
Yes you are right, java does pass by values but there are tricky situations:
if you are using primitive data type: pass by value works fine.
if you use Objects instead of primitive data type: pass by value works but for address of passing object. So it looks like passing reference.
I know concept almost look like same but technically, it is pass by value.
Have a look at this link
so I have this one problem with Gson I just cannot figure out.
Imagine a Json structure for handling tickets. The Json looks like this:
{
"concertTicket" : { ... some valid json object ... }
}
I wrote my parser like this:
#SerializedName("concertTicket")
JsonObject ticketContent;
This is simple. Now I have a JsonObject called ticketContent that stores the ticket related stuff.
So far so good... now there are exactly three different kinds of tickets: let's assume concertTicket, planeTicket and museumTicket.
What I want to achieve is a Parser with two variables. One storing the ticketType and another one storing the ticketContents.
I figured out the parser for the ticketContent:
#SerializedName(value="concertTicket", alternate={"planeTicket", "museumTicket"})
JsonObject ticketContent;
My question is now: Is it possible to write an annotation that returns the Json-Key as String in a variable called ticketType? Like so:
# ... what to put here ? ...
String ticketType;
So that
if its a concertTicket, the value of ticketType = "concertTicket",
if its a planeTicket, the value of ticketType = "planeTicket" and
if its a museumTicket, the value of ticketType = "museumTicket"?
--- Here is my workaround ---
#SerializedName( "concertTicket" )
private JsonObject concertTicket;
#SerializedName( "planeTicket" )
private JsonObject planeTicket;
#SerializedName( "museumTicket" )
private JsonObject museumTicket;
public enum TicketType {
concertTicket, planeTicket, museumTicket
}
/*
* since only one of the TicketTypes can be not null, return this as TicketType
*/
public TicketType getTicketType() {
if ( concertTicket != null ) {
return TicketType.concertTicket;
}
if ( planeTicket != null ) {
return TicketType.planeTicket;
}
if ( museumTicket != null ) {
return TicketType.museumTicket;
}
return null;
}
/*
* since only one of the TicketTypes can be not null, return this as content
*/
public JsonObject getTicketContent() {
if ( concertTicket != null ) {
return concertTicket;
}
if ( planeTicket != null ) {
return planeTicket;
}
if ( museumTicket != null ) {
return museumTicket;
}
return null;
}
But I'm wondering if there is a more elegant solution to this?
If you have 3 tickets, lets say:
concertTicket, planeTicket and museumTicket
then the should have a common parent/super class in common, or an Interface...
if so; then you can deserialize to the interface and then cast to the ticket type..
Example:
interface Iticket {
void printTicket();
}
public class Ticket implements Iticket {
protected String id;
protected int price;
public static void main(String[] args) {
String ticketString = "{\"id\":\"0000\", \"price\":15}";
Gson g = new Gson();
Ticket c = g.fromJson(ticketString, Concert.class);
((Concert) c).jump();
Ticket m = g.fromJson(ticketString, Museum.class);
((Museum) m).niddle();
}
#Override
public void printTicket() {
// TODO Auto-generated method stub
}
}
class Concert extends Ticket implements Iticket {
#Override
public void printTicket() {
//
System.out.println("Loud printer");
}
public void jump() {
System.out.println("jump");
}
}
class Museum extends Ticket implements Iticket {
#Override
public void printTicket() {
System.out.println("Boring printer");
}
public void niddle() {
System.out.println("niddle");
}
}
I have 2 domain objects, User and SystemRights (It's a many to many, so 1 user can have many rights and 1 right can be owned by many users). I'm looking for a simple way to check if a user has the required rights.
User Domain
class User {
static hasMany = [systemRights: SystemRight, enterpriseUsers: EnterpriseUser]
String email;
String passwordHash;
}
SystemRight Domain
class SystemRight {
public static final String LOGIN = "LOGIN"
public static final String MODIFY_ALL_ENTERPRISES = "MODIFY_ALL_ENTERPRISES"
public static final String ADMINISTER_SYSTEM = "ADMINISTER_SYSTEM"
public static final String VALIDATE_SUPPLIER_SCORECARDS = "VALIDATE_SUPPLIER_SCORECARDS"
static hasMany = [users:User]
static belongsTo = User
String name
}
The following did not work for me:
In User.class
public boolean hasRights(List<String> requiredRights) {
def userHasRight = SystemRight.findByUserAndSystemRight (this, SystemRight.findByName(requiredRight));
// Nor this
def userHasRight = this.systemRights.contains(SystemRight.findByName(requiredRight));
}
Current Horrible Solution
public boolean hasRights(List<String> requiredRights) {
for (String requiredRight : requiredRights) {
def has = false
for (SystemRight userRight : user.systemRights) {
if (userRight.name == requiredRight) {
has = true
break;
}
}
if (has == false) {
return false;
}
}
return true
}
If you're able/willing to change things up a bit, I'd highly recommend doing the following. It will make you're life so much easier.
First, remove the hasMany for SystemRight and User from both Domains and remove the belongsTo User from SystemRight.
Next, create the Domain to represent the join table.
class UserSystemRight {
User user
SystemRight systemRight
boolean equals(other) {
if (!(other instanceof UserSystemRight)) {
return false
}
other.user?.id == user?.id && other.systemRight?.id == systemRight?.id
}
int hashCode() {
def builder = new HashCodeBuilder()
if (user) builder.append(user.id)
if (systemRight) builder.append(systemRight.id)
builder.toHashCode()
}
// add some more convenience methods here if you want like...
static UserSystemRight get(long userId, long systemRightId, String systemRightName) {
find 'from UserSystemRight where user.id=:userId and systemRight.id=:systemRightId and systemRight.name=:systemRightName',
[userId: userId, systemRightId: systemRightId, systemRightName: systemRightName]
}
}
Then, in your User class you can add this method:
Set<SystemRight> getSystemRights() {
UserSystemRight.findAllByUser(this).collect { it.systemRight } as Set
}
Then, add this to your SystemRight Domain:
Set<User> getUsers() {
UserSystemRight.findAllBySystemRight(this).collect { it.user } as Set
}
For a more detailed explenation of why this approach is full of win, aside from actually solving your problem, take a gander at this.
I would definitely try to solve this in the database.
def relevantUserRights = SystemRight.withCriteria {
eq("user", this)
"in"("name", requiredRights);
}
return relevantUserRights.size() == requiredRights.size()
How about the following?
public boolean hasRights(List<String> requiredRights) {
return null != (this.systemRights.find { requiredRights.contains(it) });
}
(Not tested: Groovy newbie here)