There’s a problem with the IDK PRC API for search that’s tripped up users in the dev2dev forums and that stymied me for the first time today while coding up a custom search application for one of our customers.
The problem is that there’s a hardcoded limitation in the IDK that prevents you from calling PortalField.forID
if the passed in object ID is less than 100. This prevents you from searching on some really useful properties, including e-mail address! For the life of me, I can’t figure out why this limitation was imposed.
The good news is that I found a workaround. It involves a quick two-file IDK patch that entails subclassing two classes. The only catch is that you need to put the child classes in the same package as the IDK (because the parent classes have package-private constructors).
Here’s the source code that does the trick.
com.plumtree.remote.prc.search.IntrinsicPortalField.java:
package com.plumtree.remote.prc.search; import com.plumtree.remote.prc.search.PortalField; import com.plumtree.remote.prc.search.xp.*; public class IntrinsicPortalField extends PortalField { private IntrinsicPortalField(IntrinsicXPPortalField xpField) { super(xpField); } public static final IntrinsicPortalField EMAIL_ADDRESS; static { EMAIL_ADDRESS = new IntrinsicPortalField(IntrinsicXPPortalField.forID(26)); } }
com.plumtree.remote.prc.search.xp.IntrinsicXPPortalField.java:
package com.plumtree.remote.prc.search.xp; import com.plumtree.openfoundation.util.XPIllegalArgumentException; public class IntrinsicXPPortalField extends XPPortalField { private IntrinsicXPPortalField(String name, boolean isSearchable, boolean isRetrievable) { super(name, isSearchable, isRetrievable); } public static IntrinsicXPPortalField forID(int propertyId) throws XPIllegalArgumentException { return new IntrinsicXPPortalField("ptportal.propertyid." + propertyId, true, true); } }
I used e-mail address (ID = 26
) as an example, but you can put any properties in there that you want. Then, when you’re setting up your search filter, just use IntrinsicPortalField
instead of PortalField
. For example:
IFilterClause filter = searchFactory.createOrFilterClause(); filter.addStatement(IntrinsicPortalField.EMAIL_ADDRESS, Operator.Contains, searchQuery);
Since IntrinsicPortalField
is a subclass of PortalField
, the PRC has no problem with it. I’ve tested this with e-mail address and it works flawlessly. I’m sure other properties will work perfectly well too.
Enjoy!
Comments
Comments are listed in date ascending order (oldest first)
- Thank you, Chris 🙂 Now that Chris has kindly posted a workaround, any possibility of having this put into an IDK hotfix?
Posted by: ewwhitley on August 27, 2006 at 2:39 PM
- I second Eric’s opinion. Can you guys just remove the artificial restriction of 100 from the IDK in the next release? Seems to work fine without it and it would obviate the need for my silly patch.
Posted by: bucchere on August 30, 2006 at 2:31 PM
- Here is an e-mail I received from a person who attempted to use my patch:
I found your blog because I am having the same problem you describe with searching Intrinsic properties. However, I am now having trouble actually “patching” the IDK. How exactly would I go about repackaging everything with these new java files included? Thank you very much for your time and help.
Here was my response:
Thanks for your note. Assuming that you’re building a Java web application, all you need to do is compile the patch along with all your other application code. You can put the class files for the patch in
WEB-INF/classes
or you can make a jar (e.g.myapp.jar
) and put the class files for the IDK patch there and then drop the jar inWEB-INF/lib
. You can then put everything into a.war
or.ear
(or not).The magic of the Java classloader is that all the
.class
files inWEB-INF/classes
and all your.class
files inside jars inWEB-INF/lib
all end up loaded into the same memory. That means that if you have two class files in two different jars, but they’re both in thecom.plumtree.remote.portlet
package (meaning you have the linepackage com.plumtree.remote.portlet;
at the top of your source files and your.java
files live incom/plumtree/remote/portlet
), then they’ll act like they’re in the same package. This means that you’ll have access to all package private member methods, which the patch needs in order to compile.Posted by: bucchere on August 30, 2006 at 7:23 PM
- Hi mate, I think this is very helpfull but I was wondering where can I find corresponding ID’s for all standart and custom user properties, when I’m using
forID(26) method? Thanks in advance!
Posted by: ggeorgiev on September 19, 2006 at 1:16 AM
- This gets you the standard (intrinsic) ones:
select objectid, name from plumdbuser.ptproperties order by objectid where objectid < 200; 1 Name 2 Description 3 Object Created 4 Object Last Modified 5 Open Document URL 6 Content Type ID 7 Plumtree Document Image UUID 8 Content Language 9 Content Tag 26 Email Address 50 Full Text Content 60 Document Submit Content Source 61 Document Upload Repository Server 62 Document Upload DocID 71 Related Communities 72 Related Folders 73 Related Portlets 74 Related Experts 75 Related Content Managers 80 Snapshot Query Reference 101 Keywords 102 Subject 103 Author 104 Created 105 Document Title 106 URL 107 Category 111 Comments 112 Modified 152 Phone Number 153 Title 154 Department 155 Manager 156 Company 157 Address 158 Postal Code 159 State or Province 160 Country 161 Employee ID 162 City 163 Address 2
For the custom ones, change the where clause to
>= 200
.Posted by: bucchere on September 23, 2006 at 6:53 PM
6 replies on “Searching Intrinsic ALI Properties Using the PRC”
I know this is an old topic, but can you set the values for those fields via the IDK as well?
Sorry, I don't understand. Set the values in what context? The API allows you to set them before running a search . . . is that what you mean?
Custom uploader….provide a few fields for user to fill out and on upload (.save) to KD, apply the field values the user chose to the properties of the doc you are saving. If the user types a Description, set that property on upload and not allow the portal to get it from the physical doc metadata.
I built something like that many years ago for Columbia University. I just collected those values from a web form that I created and then posted them to the portal's existing doc upload endpoint. No need to use any APIs; you just reverse-engineer the form post. Does that make sense?
"I just collected those values from a web form " that is what I am doing.
"then posted them to the portal's existing doc upload endpoint" Not seeing how to post the doc without the api at this point and how you are setting doc properties.
Just use firebug, tamper, or some other tool that let's you inspect the contents of a form post when you upload a document through the portal UI. Then just reverse engineer the form post. Or you can contract with BDG and we'll build it for you. 🙂