I am beginner to lucene.
I have a field name fstname in document.
How can I retrieve documents having both the words "vamshi" and "sai" in the fstname field?
public class Indexer
{
public Indexer() {}
private IndexWriter indexWriter = null;
public IndexWriter getIndexWriter(boolean create) throws IOException
{
if (indexWriter == null)
{
File file=new File("D:/index-directory");
Path dirPath = file.toPath();
Directory indexDir = FSDirectory.open(file);
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_2,new StandardAnalyzer());
indexWriter = new IndexWriter(indexDir, config);
}
return indexWriter;
}
public void closeIndexWriter() throws IOException
{
if (indexWriter != null)
{
indexWriter.close();
}
}
public void indexHotel(Hotel hotel) throws IOException
{
IndexWriter writer = getIndexWriter(false);
Document doc = new Document();
doc.add(new StringField("id", hotel.getId(), Field.Store.YES));
doc.add(new StringField("fstname", hotel.getFstname(), Field.Store.YES));
doc.add(new StringField("lastname", hotel.getLastname(), Field.Store.YES));
doc.add(new LongField("mobileno", hotel.getMobileno(), Field.Store.YES));
String fullSearchableText = hotel.getId()+" "+hotel.getFstname()+ " " + hotel.getLastname() + " " + hotel.getMobileno();
doc.add(new TextField("content", fullSearchableText, Field.Store.NO));
writer.addDocument(doc);
}
public void rebuildIndexes() throws IOException
{
getIndexWriter(true);
indexWriter.deleteAll();
Hotel[] hotels = HotelDatabase.getHotels();
for(Hotel hotel : hotels)
{
indexHotel(hotel);
}
closeIndexWriter();
}
}
public class SearchEngine
{
private IndexSearcher searcher = null;
private QueryParser parser = null;
/** Creates a new instance of SearchEngine */
public SearchEngine() throws IOException
{
File file=new File("D:/index-directory");
Path dirPath = file.toPath();
searcher = new IndexSearcher(DirectoryReader.open(FSDirectory.open(file)));
parser = new QueryParser("content", new StandardAnalyzer());
}
public TopDocs performSearch(String queryString, int n)
throws IOException, ParseException
{
Query query = parser.parse(queryString);
return searcher.search(query, n);
}
public Document getDocument(int docId)
throws IOException {
return searcher.doc(docId);
}
}
public class HotelDatabase
{
private static final Hotel[] HOTELS = {
new Hotel("1","vamshi","chinta",9158191135L),
new Hotel("2","vamshi krishna","chinta",9158191136L),
new Hotel("3","krishna","chinta",9158191137L),
new Hotel("4","vamshi","something",9158191138L),
new Hotel("5","venky","abc",123456789L),
new Hotel("6","churukoti","def",123456789L),
new Hotel("7","chinta","vamshi",9158191139L),
new Hotel("8","chinta","krishna vamshi",9158191139L),
};
public static Hotel[] getHotels() {
return HOTELS;
}
public static Hotel getHotel(String id) {
for(Hotel hotel : HOTELS) {
if (id.equals(hotel.getId())) {
return hotel;
}
}
return null;
}
}
public class Hotel
{
private String fstname;
private String lastname;
private long mobileno;
private String id;
public void setMobileno(long mobileno) {
this.mobileno = mobileno;
}
public Hotel()
{
}
public Hotel(String id,
String fstname,
String lastname,
Long mobileno) {
this.id = id;
this.fstname = fstname;
this.lastname = lastname;
this.mobileno = mobileno;
}
public String getFstname() {
return fstname;
}
public void setFstname(String fstname) {
this.fstname = fstname;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public long getMobileno() {
return mobileno;
}
public void setMobileno(int mobileno) {
this.mobileno = mobileno;
}
public String toString() {
return "Hotel "
+ getId()
+": "
+ getFstname()
+" ("
+ getLastname()
+")";
}
}
now when i search with the query
TopDocs topDocs=new SearchEngine().performSearch("fstname:vamshi AND fstname:krishna", 100);
it is not returning document with fstname as "vamshi krishna"
what is the problem in my code??
This is a simple boolean AND query:
fstname:vamshi AND fstname:sai
The StandardQueryParser will translate this into the query:
+fstname:vamshi +fstname:sai
Edit:
There is one problem in your code. You are using StringFields to store the hotel names. However StringFields are only indexed but not tokenized. (see here) That means that they are not being broken down into the individual tokens. If you add "vamshi krishna" then this is not being tokenized into "vamshi" and "krishna" but just stored as "vamshi krishna".
Try using a regular TextField and it should work.
Try using these:
fstname:vamshi*sai OR fstname:sai*vamshi
As you can see this is searching for text pattern. This probably will gonna have performance issues.
Try looking here for more information.
Related
I am working on migrating solr from 5.4.3 to 8.11 for one of my search apps and successfully upgraded to 7.7.3. But for further upgradations facing the order of the response data being changed than it was earlier. Here I am trying to use FunctionScoreQuery along with DoubleValuesSource since CustomScoreQuery is deprecated in 7.7.3 and removed in 8.
Below is my code snippet (now I am using solr 8.5.2 and Lucene 8.5.2)
public class CustomQueryParser extends QParserPlugin {
#Override
public QParser createParser(final String qstr, final SolrParams localParams, final SolrParams params,
final SolrQueryRequest req) {
return new MyParser(qstr, localParams, params, req);
}
private static class MyParser extends QParser {
private Query innerQuery;
private String queryString;
public MyParser(final String qstr, final SolrParams localParams, final SolrParams params,
final SolrQueryRequest req) {
super(qstr, localParams, params, req);
if (qstr == null || qstr.trim().length() == 0) {
this.queryString = DEFAULT_SEARCH_QUERY;
setString(this.queryString);
} else {
this.queryString = qstr;
}
try {
if (queryString.contains(":")) {
final QParser parser = getParser(queryString, "edismax", getReq());
this.innerQuery = parser.parse();
} else {
final QParser parser = getParser(queryString, "dismax", getReq());
this.innerQuery = parser.parse();
}
} catch (final SyntaxError ex) {
throw new RuntimeException("Error parsing query", ex);
}
}
#Override
public Query parse() throws SyntaxError{
final Query query = new MyCustomQuery(innerQuery);
final CustomValuesSource customValuesSource = new CustomValuesSource(queryString,innerQuery);
final FunctionScoreQuery fsq = FunctionScoreQuery.boostByValue(query, customValuesSource.fromFloatField("score"));
return fsq;
}
}
}
public class MyCustomQuery extends Query {
#Override
public Weight createWeight(final IndexSearcher searcher, final ScoreMode scoreMode, final float boost) throws IOException {
Weight weight;
if(query == null){
weight = new ConstantScoreWeight(this, boost) {
#Override
public Scorer scorer(final LeafReaderContext context) throws IOException {
return new ConstantScoreScorer(this,score(),scoreMode, DocIdSetIterator.all(context.reader().maxDoc()));
}
#Override
public boolean isCacheable(final LeafReaderContext leafReaderContext) {
return false;
}
};
}else {
weight = searcher.createWeight(query,scoreMode,boost);
}
return weight;
}
}
public class CustomValuesSource extends DoubleValuesSource {
#Override
public DoubleValues getValues(final LeafReaderContext leafReaderContext,final DoubleValues doubleValues) throws IOException {
final DoubleValues dv = new CustomDoubleValues(leafReaderContext);
return dv;
}
class CustomDoubleValues extends DoubleValues {
#Override
public boolean advanceExact(final int doc) throws IOException {
final Document document = leafReaderContext.reader().document(doc);
final List<IndexableField> fields = document.getFields();
for (final IndexableField field : fields) {
// total_score is being calculated with my own preferences
document.add(new FloatDocValuesField("score",total_score));
//can we include the **score** here?
this custom logic which includes score is not even calling.
}
}
}
I am trying for a long time but have not found a single working example. Can anybody help me and save me here.
Thank you,
Syamala.
I'm using Ignite 2.1.0 and I create a simple program to try DataStreamer, but I offen got error like this:
"[diagnostic]Failed to wait for partition map exchange" or "Attempted to release write lock while not holding it".
I started two local nodes, one was started in windows CMD using example xml configuration and another was started in Eclipse. My code in Eclipse like this :
public class TestDataStreamer {
public static void main(String[] args) {
// TODO Auto-generated method stub
long bgn,end;
IgniteConfiguration cfg = new IgniteConfiguration();
cfg.setPeerClassLoadingEnabled(true);
Ignite ignite = Ignition.start(cfg);
CacheConfiguration<Long, Map> cacheConf = new CacheConfiguration();
cacheConf.setName("TestDataStreamer").setCacheMode(CacheMode.REPLICATED);
cacheConf.setBackups(0);
IgniteCache cache = ignite.getOrCreateCache(cacheConf);
cache.clear();
File dataFile = new File("D:/data/1503307171374.data"); //10,000,000 rows text data
bgn = System.currentTimeMillis();
try {
loadByStreamer(dataFile,ignite,"TestDataStreamer");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
end = System.currentTimeMillis();
System.out.println("---------------");
System.out.println((end-bgn)/1000.0+" s");
}
cache.destroy();
System.out.println("cache destroy...");
ignite.close();
System.out.println("finish");
}
private static void loadByStreamer(File dataFile, Ignite ignite, String cacheName) throws Exception {
IgniteDataStreamer<Long,TestObj> ds = ignite.dataStreamer(cacheName);
//ds.allowOverwrite(true);
ds.autoFlushFrequency(10000);
ds.perNodeBufferSize(4096);
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(dataFile),"UTF-8"));
String line = null;
long count = 0;
while((line=br.readLine())!=null){
ds.addData(System.currentTimeMillis(), parseData(line, Constants.DEFAULT_SEPARATOR,
"id,sn,type_code,trade_ts,bill_ts,company_code,company_name,biz_type,charge_amt,pay_mode".split(",")));
if(++count%10000==0){
System.out.println(count+" loaded...");
}
//System.out.println(count+":"+line);
}
System.out.println("flushing...");
ds.flush();
System.out.println("flushed");
br.close();
ds.close();
System.out.println("file handled...");
}
private static TestObj parseData(String data, String saperator, String[] fields){
TestObj obj = new TestObj();
if(data!=null && saperator.trim().length()>0){
String[] values = data.split(saperator);
obj.setId(values[0]);
obj.setSn(values[1]);
obj.setType_code(values[2]);
obj.setTrade_ts(values[3]);
obj.setBill_ts(values[4]);
obj.setCompany_code(values[5]);
obj.setCompany_name(values[6]);
obj.setBiz_type(values[7]);
obj.setCharge_amt(values[8]);
obj.setPay_mode(values[9]);
}
return obj;
}
}
class TestObj {
private String id;
private String sn;
private String type_code;
private String trade_ts;
private String bill_ts;
private String company_code;
private String company_name;
private String biz_type;
private String charge_amt;
private String pay_mode;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getType_code() {
return type_code;
}
public void setType_code(String type_code) {
this.type_code = type_code;
}
public String getTrade_ts() {
return trade_ts;
}
public void setTrade_ts(String trade_ts) {
this.trade_ts = trade_ts;
}
public String getBill_ts() {
return bill_ts;
}
public void setBill_ts(String bill_ts) {
this.bill_ts = bill_ts;
}
public String getCompany_code() {
return company_code;
}
public void setCompany_code(String company_code) {
this.company_code = company_code;
}
public String getCompany_name() {
return company_name;
}
public void setCompany_name(String company_name) {
this.company_name = company_name;
}
public String getBiz_type() {
return biz_type;
}
public void setBiz_type(String biz_type) {
this.biz_type = biz_type;
}
public String getCharge_amt() {
return charge_amt;
}
public void setCharge_amt(String charge_amt) {
this.charge_amt = charge_amt;
}
public String getPay_mode() {
return pay_mode;
}
public void setPay_mode(String pay_mode) {
this.pay_mode = pay_mode;
}
}
If stop the node started in CMD and run the program in only one node, it works well.
Is there anyone can help me?
Update jdk for both nodes to the same version, for example for 1.8.0_144(as you already have it in installed), or at least, try to update idk in eclipse to the latest of 1.7 versions, it should help.
There is a thread on Ignite user list, when guys faced pretty the same exception and updating of java version helped them to fix it.
I am getting the below exception:
Could not find PortableFactory for factory-id: 1
com.hazelcast.nio.serialization.HazelcastSerializationException: Could
not find PortableFactory for factory-id: 1
On the client side I have the following code:
public class ClientTest {
public static void main(String[] args) {
List<String> nodes = new ArrayList<String>();
nodes.add("localhost:5701");
ClientConfig clientConfig = new ClientConfig();
ClientNetworkConfig networkConfig = new ClientNetworkConfig();
networkConfig.setAddresses(nodes);
clientConfig.setNetworkConfig(networkConfig);
SerializationConfig serCong = clientConfig.getSerializationConfig();
serCong.addPortableFactory(1, new UserFactoryImpl());
serCong.setPortableVersion(1);
HazelcastInstance hzClient1 = HazelcastClient.newHazelcastClient(clientConfig);
IMap<String, User> map = hzClient1.getMap("user");
System.out.println(map.size() + "hiten");
User user1 = new User();
user1.setFirstName("hiten");
user1.setLastName("singh");
map.put("1", user1);
//hz1.getLifecycleService().terminate();
System.out.println(map.size() + "after");
User user2 = new User();
user2.setFirstName("hiten1");
user2.setLastName("singh1");
map.put("2", user2);
UserEntryProcessor entryProc = new UserEntryProcessor();
User userRes = (User)map.executeOnKey("1", entryProc);
}
static class UserEntryProcessor implements EntryProcessor<String, User>, HazelcastInstanceAware {
private transient HazelcastInstance hazelcastInstance;
#Override
public Object process(Entry<String, User> entry) {
User user = entry.getValue();
if(user != null) {
System.out.println(user.getFirstName());
}
return user;
}
#Override
public EntryBackupProcessor<String, User> getBackupProcessor() {
return null;
}
#Override
public void setHazelcastInstance(HazelcastInstance hazelcastInstance) {
this.hazelcastInstance = hazelcastInstance;
}
}
static class UserFactoryImpl implements PortableFactory{
public final static int USER_PORTABLE_ID = 1;
public final static int FACTORY_ID = 1;
public Portable create(int classId) {
switch (classId) {
case USER_PORTABLE_ID:
return new User();
}
return null;
}
}
static class User implements Portable {
private String firstName;
private String lastName;
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Override
public int getFactoryId() {
return UserFactoryImpl.FACTORY_ID;
}
#Override
public int getClassId() {
return UserFactoryImpl.USER_PORTABLE_ID;
}
#Override
public void writePortable(PortableWriter writer) throws IOException {
writer.writeUTF("first_name", firstName);
writer.writeUTF("last_name", lastName);
}
#Override
public void readPortable(PortableReader reader) throws IOException {
firstName = reader.readUTF("first_name");
lastName = reader.readUTF("last_name");
}
}
}
Yes it does, just as you figured out the factory and the classes need to be available. Currently there is no built-in solution to not share classes for more sophisticated use cases than simple gets / puts. I have JSON support and some other ideas cooking but nothing really done yet.
I'm trying to deserialize JSON from Reddit that you can obtain by appending .json to the url. An example would be:
http://www.reddit.com/r/pics/comments/1wvx52/.json?sort=top
However, I am getting the error message:
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 9765
At line 1 column 9765 in the json there is the following code: "replies": "", whereas normally this would contain an object like this: replies: {
kind: "Listing",
data: {}
},
Does this mean that the json is a String when there is no data, but an object otherwise? How can I deserialize with gson properly if this is the case? I've included my classes below. I still need to figure out how to handle the json starting off with an array of basically two different objects (the first listing in the json is describing the link, while the second listing is describing the comments), but I'll cross that bridge when I get there. Thanks in advance if anyone can shed some light on this issue.
Main Class
public static void main(String[] args)
{
ArrayList<CommentsResults> commentsResults = new ArrayList<CommentsResults>();
String commentsURL = "http://www.reddit.com/r/pics/comments/1wvx52/.json?sort=top";
URL url = null;
try
{
url = new URL(commentsURL);
} catch (MalformedURLException ex)
{
System.out.println(ex.getMessage());
}
try
{
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
String jsonText = readAll(bufferedReader);
Gson gson = new GsonBuilder().create();
commentsResults = gson.fromJson(jsonText, new TypeToken<ArrayList<CommentsResults>>(){}.getType());
} catch (IOException ex)
{
System.out.println(ex.getMessage());
}
}
private static String readAll(Reader reader) throws IOException
{
StringBuilder stringBuilder = new StringBuilder();
int cp;
while ((cp = reader.read()) != -1)
{
stringBuilder.append((char) cp);
}
return stringBuilder.toString();
}
CommentsResults Class
public class CommentsResults {
private String kind;
private CommentsData data;
public CommentsResults()
{
}
public CommentsResults(String kind, CommentsData data)
{
this.kind = kind;
this.data = data;
}
public String getKind()
{
return kind;
}
public CommentsData getData()
{
return data;
}
public void setKind(String kind)
{
this.kind = kind;
}
public void setData(CommentsData data)
{
this.data = data;
}
}
CommentsData Class
private String modhash;
private List <CommentsChild> children;
public CommentsData()
{
}
public CommentsData(String modhash, List<CommentsChild> children)
{
this.modhash = modhash;
this.children = children;
}
public String getModhash()
{
return modhash;
}
public List<CommentsChild> getChildren()
{
return children;
}
public void setModhash(String modhash)
{
this.modhash = modhash;
}
public void setChildren(List<CommentsChild> children)
{
this.children = children;
}
CommentsChild Class
private String kind;
private Comment data;
public CommentsChild()
{
}
public CommentsChild(String kind, Comment comment)
{
this.kind = kind;
this.data = comment;
}
public String getKind()
{
return kind;
}
public Comment getComment()
{
return data;
}
public void setKind(String kind)
{
this.kind = kind;
}
public void setComment(Comment comment)
{
this.data = comment;
}
Comment Class
public class Comment {
private CommentsResults replies;
private String id;
private int gilded;
private String author;
private String parent_id;
private String body;
private int downs;
private String link_id;
private boolean score_hidden;
private int created_utc;
private String distinguished;
public Comment()
{
}
public Comment(CommentsResults replies, String id, int gilded, String author, String parent_id, String body, int downs, String link_id, boolean score_hidden, int created_utc, String distinguished)
{
this.replies = replies;
this.id = id;
this.gilded = gilded;
this.author = author;
this.parent_id = parent_id;
this.body = body;
this.downs = downs;
this.link_id = link_id;
this.score_hidden = score_hidden;
this.created_utc = created_utc;
this.distinguished = distinguished;
}
public CommentsResults getReplies()
{
return replies;
}
public String getId()
{
return id;
}
public int getGilded()
{
return gilded;
}
public String getAuthor()
{
return author;
}
public String getParent_id()
{
return parent_id;
}
public String getBody()
{
return body;
}
public int getDowns()
{
return downs;
}
public String getLink_id()
{
return link_id;
}
public boolean isScore_hidden()
{
return score_hidden;
}
public int getCreated_utc()
{
return created_utc;
}
public String getDistinguished()
{
return distinguished;
}
public void setReplies(CommentsResults replies)
{
this.replies = replies;
}
public void setId(String id)
{
this.id = id;
}
public void setGilded(int gilded)
{
this.gilded = gilded;
}
public void setAuthor(String author)
{
this.author = author;
}
public void setParent_id(String parent_id)
{
this.parent_id = parent_id;
}
public void setBody(String body)
{
this.body = body;
}
public void setDowns(int downs)
{
this.downs = downs;
}
public void setLink_id(String link_id)
{
this.link_id = link_id;
}
public void setScore_hidden(boolean score_hidden)
{
this.score_hidden = score_hidden;
}
public void setCreated_utc(int created_utc)
{
this.created_utc = created_utc;
}
public void setDistinguished(String distinguished)
{
this.distinguished = distinguished;
}
}
So in the off chance this helps somebody (which seems dubious at this point) I decided to parse the Json manually using recursion. Here's how I did it:
public static void getCommentsOnLink()
{
String commentsURL= "http://www.reddit.com/r/pics/comments/1wvx52/.json?sort=top";
URL url = null;
try
{
url = new URL(commentsURL);
} catch (MalformedURLException ex)
{
System.out.println(ex.getMessage());
}
String JsonText = readCommentJsonFromURL(url);
RedditCommentResults redditCommentResults = getCommentResults(JsonText);
}
private static String readCommentJsonFromURL(URL url)
{
String JSONText = null;
try
{
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
JSONText = readAll(bufferedReader);
} catch (IOException ex)
{
System.out.println(ex.getMessage());
}
return JSONText;
}
private static String readAll(Reader reader) throws IOException
{
StringBuilder stringBuilder = new StringBuilder();
int cp;
while ((cp = reader.read()) != -1)
{
stringBuilder.append((char) cp);
}
return stringBuilder.toString();
}
private static RedditCommentResults getCommentResults(String JsonText)
{
JsonParser parser = new JsonParser();
JsonArray completeJson = (JsonArray) parser.parse(JsonText);
//get link and comment object from the array containing an object for each
JsonObject linkParentJson = (JsonObject) completeJson.get(0);
JsonObject commentParentJson = (JsonObject) completeJson.get(1);
//use automatic deserializer for redditLink
JsonObject linkListingDataJson = linkParentJson.getAsJsonObject("data");
JsonObject linkChildrenJson = linkListingDataJson.getAsJsonArray("children").get(0).getAsJsonObject();
JsonObject linkDataJson = linkChildrenJson.getAsJsonObject("data");
Link commentLink = gson.fromJson(linkDataJson, Link.class);
RedditLink redditCommentLink = new RedditLink(commentLink);
//parse comments manually
JsonObject commentDataJson = commentParentJson.getAsJsonObject("data");
JsonArray commentChildrenJson = commentDataJson.getAsJsonArray("children");
//get all of the comments from the JsonArray
ArrayList<RedditComment> redditComments = getNestedComments(commentChildrenJson);
RedditCommentResults redditCommentResults = new RedditCommentResults(redditComments, redditCommentLink);
return redditCommentResults;
}
private static ArrayList<RedditComment> getNestedComments(JsonArray commentWrapperJsonArray)
{
ArrayList<RedditComment> redditComments = new ArrayList();
for (JsonElement commentWrapperJson : commentWrapperJsonArray)
{
//cast Element to Object so we can search for the primitive "kind". Finally we get it as a String
String kind = commentWrapperJson.getAsJsonObject().getAsJsonPrimitive("kind").getAsString();
//if the comment is of type t1 meaning it is a comment and not a "more" (a "more" is a comment which
//hasn't been loaded yet because it does not have a great deal of upvotes relative to other comments)
if (kind.equals("t1"))
{
JsonObject commentJson = commentWrapperJson.getAsJsonObject().getAsJsonObject("data");
Comment comment = gson.fromJson(commentJson, Comment.class);
RedditComment redditComment = new RedditComment(comment);
JsonElement repliesJson = commentJson.get("replies");
//if the reply is not equal to an empty String (i.e. if there is at least one reply)
if (!repliesJson.isJsonPrimitive())
{
JsonObject dataJson = repliesJson.getAsJsonObject().getAsJsonObject("data");
JsonArray childrenJson = dataJson.getAsJsonArray("children");
ArrayList<RedditComment> nestedComments = getNestedComments(childrenJson);
redditComment.setReplies(nestedComments);
}
redditComments.add(redditComment);
}
}
return redditComments;
}
You have to remove the private CommentsResults replies; from Comment Class and compose replies in CommentsChild class. According to Json fomate you model is
CommentResult -
CommentsData --
List <CommentsChild> children---
CommentsResults replies
recursion/ repeation of comment result
public class CommentsChild {
private String kind;
private Comment data;
//
private CommentsResults replies;
}
I am stuck in one of the issue. Suppose i have a phone number field 010-9999-9999, this number should split in 3 text field. I tried to do this but i get only prefix number i.e 010 in all three text field. I am using jface databinding.
I created Model as
class A{
String phoneNo;
}
Jface Databinding:
IObservableValue ssn1TextTextObserveWidget = SWTObservables.observeText(text_ph11, SWT.Modify);
IObservableValue ssn2TextTextObserveWidget = SWTObservables.observeText(text_ph2, SWT.Modify);
IObservableValue ssn2TextTextObserveWidget1 = SWTObservables.observeText(text_ph3, SWT.Modify);
IObservableValue simpleTableViewerSSN1ObserveDetailValue = BeansObservables.observeDetailValue(simpleTableViewerSelectionObserveSelection_employee, "phoneNo", String.class);
IObservableValue simpleTableViewerSSN2ObserveDetailValue = BeansObservables.observeDetailValue(simpleTableViewerSelectionObserveSelection_employee, "phoneNo", String.class);
IObservableValue simpleTableViewerSSN2ObserveDetailValue = BeansObservables.observeDetailValue(simpleTableViewerSelectionObserveSelection_employee, "phoneNo", String.class);
Databinding
bindingContext.bindValue(simpleTableViewerSSN1ObserveDetailValue, ssn1TextTextObserveWidget, null, null);
bindingContext.bindValue(simpleTableViewerSSN2ObserveDetailValue, ssn2TextTextObserveWidget, null, null);
bindingContext.bindValue(simpleTableViewerSSN2ObserveDetailValue, ssn2TextTextObserveWidget1, null, null);
When i try to do this value only prefix get populated in all three fields i.e 010-010-010. Please help me out to resolve this issue.
If you want your phone number to be divided into three different widgets you will probably need to save the phone number in three different attributes, each assigned a different part of the phone number.
There might be some way to bind a 'part' of a string value to a widget, maybe through getter methods, but for that wait and let someone more knowledgeable in this area give an answer for you.
Here is sample code that can be modified to work with your case. IConverter is used with UpdateValueStrategy to modify the value that will be set/get model to/from target text feild.
//GUI class
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout(3, false));
Label lbl = new Label(shell, SWT.NONE);
lbl.setText("Name");
final Text firstName = new Text(shell, SWT.BORDER);
final Text lastName = new Text(shell, SWT.BORDER);
final Name name = new Name();
SWTObservables.getRealm(display).exec(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Realm realm = SWTObservables.getRealm(display);
DataBindingContext cxt = new DataBindingContext(realm);
ISWTObservableValue firstNameObservable = SWTObservables.observeText(firstName, new int[] { SWT.Modify });
ISWTObservableValue lastNameObservable = SWTObservables.observeText(lastName, new int[] { SWT.Modify });
final IObservableValue nameObservable = BeansObservables.observeValue(realm, name, "name");
UpdateValueStrategy firstNameTxtToName = new UpdateValueStrategy();
firstNameTxtToName.setConverter(new IConverter() {
#Override
public Object getToType() {
// TODO Auto-generated method stub
return String.class;
}
#Override
public Object getFromType() {
// TODO Auto-generated method stub
return String.class;
}
#Override
public Object convert(Object fromObject) {
String val = fromObject.toString();
Object beanVal = nameObservable.getValue();
if (beanVal != null) {
String beanString = beanVal.toString();
int i = beanString.indexOf(',');
if (i != -1) {
return val + beanString.substring(i);
}
}
return val;
}
});
UpdateValueStrategy nameToFirstName = new UpdateValueStrategy();
nameToFirstName.setConverter(new IConverter() {
#Override
public Object getToType() {
// TODO Auto-generated method stub
return String.class;
}
#Override
public Object getFromType() {
// TODO Auto-generated method stub
return String.class;
}
#Override
public Object convert(Object fromObject) {
if (fromObject != null) {
Object objVal = nameObservable.getValue();
if (objVal != null) {
String val = objVal.toString();
int i = val.indexOf(',');
if (i != -1) {
return val.substring(0, i);
} else {
return val;
}
}
}
return "";
}
});
UpdateValueStrategy lastNameTxtToName = new UpdateValueStrategy();
lastNameTxtToName.setConverter(new IConverter() {
#Override
public Object getToType() {
// TODO Auto-generated method stub
return String.class;
}
#Override
public Object getFromType() {
// TODO Auto-generated method stub
return String.class;
}
#Override
public Object convert(Object fromObject) {
String val = fromObject.toString();
Object beanVal = nameObservable.getValue();
if (beanVal != null) {
String beanString = beanVal.toString();
int i = beanString.indexOf(',');
String fName = beanString;
if (i != -1) {
fName = beanString.substring(0, i + 1);
} else {
fName = fName + ",";
}
val = fName + val;
}
return val;
}
});
UpdateValueStrategy nameToLastName = new UpdateValueStrategy();
nameToLastName.setConverter(new IConverter() {
#Override
public Object getToType() {
// TODO Auto-generated method stub
return String.class;
}
#Override
public Object getFromType() {
// TODO Auto-generated method stub
return String.class;
}
#Override
public Object convert(Object fromObject) {
if (fromObject != null) {
String val = fromObject.toString();
int i = val.indexOf(',');
if (i != -1) {
return val.substring(i + 1);
}
}
return "";
}
});
cxt.bindValue(firstNameObservable, nameObservable, firstNameTxtToName, nameToFirstName);
cxt.bindValue(lastNameObservable, nameObservable, lastNameTxtToName, nameToLastName);
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
//POJO
public class Name {
private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
changeSupport.addPropertyChangeListener(propertyName, listener);
}
public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
changeSupport.removePropertyChangeListener(propertyName, listener);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
changeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
changeSupport.removePropertyChangeListener(listener);
}
public void firePropertyChangeEvent(PropertyChangeEvent evt) {
changeSupport.firePropertyChange(evt);
}
String name;
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
System.out.println(name);
}
}