I am very new to xpages. I have been searching the web for an answer to my question for a while now. Seems like the answer should be simple.
I have been playing around with a snippet of code that I got from Brad Balassaitis's excellent Xcellerent.net site that populates a list of "jumptoitems" for a viewpanel dynamically. The code is run from the beforeRenderResponse event of the xpage.
var viewName = getComponent('viewPanel1').getData().getViewName();
var vw = database.getView(viewName);
var colNum = 1;
var cols:Vector = vw.getColumns();
for (var i=0; i < cols.length; i++) {
if (cols[i].isSorted() && !cols[i].isHidden()) {
colNum = i + 1;
break;
}
}
var letters = #DbColumn(null, viewName, colNum);
var options = #Trim(#Unique(#UpperCase(#Left(letters, 1))))
viewScope.put('jumpToOptions', options);
It works beautifully - but I want to modify the code to reference a view in a different database. In the post Brad says that the code can be "enhanced" to accomplish this. But I have been experimenting and searching for a while and cannot accomplish the enhancement.
Thanks for any help.
--Lisa&
In your second line, you establish a handle on the view by viewName you pull from the component viewPanel1. Your call is database.getView(viewName). This amounts to a programmatic reference of NotesDatabase.getView(). If you get a handle on the other database you want to connect to, they you can invoke the same .getView() call on that handle.
First, establish your connection to the other database; this is done via the session keyword (which is a NotesSession), as such:
var extDB = session.getDatabase(dbName)
As Howard points out, that session keyword is the current user's session and will be subject to all ACL rights/assignments/roles as that user. If you need to elevate privileges to programmatically expose additional data, you can do so with the sessionAsSigner keyword (which is also a NotesSession, just with the credentials of the signer, yourself, or you can have the NSF signed as the server ID, to give it even higher privileges).
Then proceed as usual with your extDB handle in place of the database keyword (which is about the same as session.getCurrentDatabase()); like so:
var vw = extDB.getView(viewName)
The NotesDatabase.getView() call will return null if a View by that name doesn't exist in that NSF, so you'll want to ensure that it's there and programmatically check for and handle a null return.
[Edit]
Since you're using the ported # function of #DbColumn as it is, to use the approach as Frantisek Kossuth suggests may be easy, but relies on the NotesSession of the current user. To override that user's (lack of) privileges and get full visibility of all documents' values in the separate NSF, you would still need to get a handle on the columnValues for the View as shown above, using the sessionAsSigner keyword.
[/Edit]
Based on your code you need to specify database in #DbColumn formula, too.
var letters = #DbColumn([database], viewName, colNum);
You can read about it here or there...
Aside of documented formats you can use API format "server!!database" as single string value.
Related
Is there any way to inspect or enumerate the Custom Slot Values that are set-up in your interaction model? For Instance, Say you have an intent schema with the following intent:
{
"intent": "MySuperCoolIntent",
"slots":
[
{
"name": "ShapesNSuch",
"type": "LIST_OF_SHAPES"
}
]
}
Furthermore, you've defined the LIST_OF_SHAPES Custom Slot to have the following Values:
SQUARE
TRIANGLE
CIRCLE
ICOSADECAHECKASPECKAHEDRON
ROUND
HUSKY
Question: is there a method I can call from my Speechlet or my RequestStreamHandler that will give me an enumeration of those Custom Slot Values??
I have looked through the Alexa Skills Kit's SDK Javadocs Located Here
And I'm not finding anything.
I know I can get the Slot's value that is sent in with the intent:
String slotValue = incomingIntentRequest.getIntent().getSlot("LIST_OF_SHAPES").getValue();
I can even enumerate ALL the incoming Slots (and with it their values):
Map<String, Slot> slotMap = IncomingIntentRequest.getIntent().getSlots();
for(Map.Entry<String, Slot> entry : slotMap.entrySet())
{
String key = entry.getKey();
Slot slot = (Slot)entry.getValue();
String slotName = slot.getName();
String slotValue = slot.getValue();
//do something nifty with the current slot info....
}
What I would really like is something like:
String myAppId = "amzn1.echo-sdk-ams.app.<TheRestOfMyID>";
List<String> posibleSlotValues = SomeMagicAlexaAPI.getAllSlotValues(myAppId, "LIST_OF_SHAPES");
With this information I wouldn't have to maintain two separate "Lists" or "Enumerations"; One within the interaction Model and another one within my Request Handler. Seems like this should be a thing right?
No, the API does not allow you to do this.
However, since your interaction model is intimately tied with your development, I would suggest you check in the model with your source code in your source control system. If you are going to do that, you might as well put it with your source. Depending on your language, that also means you can probably read it during run-time.
Using this technique, you can gain access to your interaction model at run-time. Instead of doing it automatically through an API, you do it by best practice.
You can see several examples of this in action for Java in TsaTsaTzu's examples.
No - there is nothing in the API that allows you to do that.
You can see the full extent of the Request Body structure Alexa gives you to work with. It is very simple and available here:
https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#Request%20Format
Please note, the Request Body is not to be confused with the request, which is a structure in the request body, with two siblings: version and session.
I am new to snmp and using snmp4j to create an snmp agent.My java application needs to listen to snmp request and query the db based on the incoming oid and send a response back. I have a src code for snmp agent. But how does the agent query the db based on the incoming oid? Do I need to register all oids in my db as managed objects in the agent so the agent can do the look up when the request arrives? or in other words, how do i point to my datastore/db from the agent?
this is the code i am using.
http://shivasoft.in/blog/java/snmp/creating-snmp-agent-server-in-java-using-snmp4j/
`List oidList = impl.getOidList(); //get data from db
for (Oid oid : oidList) {
agent.registerManagedObject(MOScalarFactory.createReadOnly(new OID(
oid.getOid()), oid.getValue()));
}'
I am trying to register the managed objects with data in db. Is this correct?
I am getting duplicate registration exception on second row though the oid is unique.
`.1.3.6.1.4.1.1166.1.6.1.2.2.1.3.1.1
.1.3.6.1.4.1.1166.1.6.1.2.2.1.3.1.2`
I dont think this is the right way because what if the db is huge?
Any help/tips are greatly appreciated.
Problem
You get org.snmp4j.agent.DuplicateRegistrationException because there can be only one ManagedObject in the ContextScope. Each registration assigns ManagedObject value to the MOContextScope. Second registration tries to set second object to the contextScope. The scope is already filled and thus exception is thrown.
Althow each scalar value SHOULD end up with .0. You may check any MIB browser like iReasoning and pick any value. If this value is scalar - trailing zero is appended automaticaly despite the fact it is not mentioned in MIB-file. So the most "correct" way is to use 4.1 solution.
Solution 1 - own MOScalar
Write your own MOScalar. With tinier bounds.
You should overwrite getLowerBound, getUpperBound, isLowerIncluded, isUpperIncluded to get separate contextScopes for your objects.
I would suggest to return Scalar OID every time and include both boundaries.
Upper and lower boundaries better return same OID you've settled.
Solution 2 - own MOServer
Write your own MOServer. With blackJack and others...
Mostly you can simply copypaste code despite this one
private SortedMap<MOScope, ManagedObject> registry;
It should look like this
private SortedMap<MOScope, Set<ManagedObject>> registry;
And it would affect registration, unregistration and other logic.
DefaultMOServer - 678 lines incl. comments. In fact you should fix several classes:
query.matchesQuery(object)
private boolean matchesQuery(MOQuery query, ManagedObject object) {
if ((query.matchesQuery(object)) && object.getScope().isOverlapping(query.getScope()))
if (object instanceof MOScalar) {
MOScalar moScalar = (MOScalar) object;
return query.getLowerBound().compareTo(moScalar.getID()) <= 0 &&
query.getUpperBound().compareTo(moScalar.getID()) >= 0;
} else {
return true;
}
return false;
}
protected void fire...Event(ManagedObject objects, MOQuery query) {
protected void fire...Event(Set<ManagedObject> objects, MOQuery query) {
if (lookupListener != null) {
for (ManagedObject mo : objects) {
ManagedObject other = lookup(new DefaultMOQuery(contextScope));
Set<ManagedObject> other = lookup(new DefaultMOQuery(contextScope), false);
And so on...
Solution 3 - Tables
Use table rows.
You can add a table and append rows.
You would be able to access cells as the
<tableEntryOID>.<columnSubID>.<rowIndexOID>
You may use this question as tutorial.
Solution 4 - OIDs fixup
Make you oid's use different contextScopes.
Solution 4.1
Adding trailing zero
agent.registerManagedObject(
MOScalarFactory.createReadOnly(
new OID(oid.getOid()).successor(),
oid.getValue()
)
);
This will append .0 to the same-level properties.
snmpget -v2c -c public localhost:2001 oid.getOid().0
Also any MIBbrowser will append .0 to each scalar oid defined in the MIB-file. You may check it with iReasoning as the most popular browser. Even hrSystemUptime (.1.3.6.1.2.1.25.1.1 - see left bottom) is requested as hrSystemUptime.0 (.1.3.6.1.2.1.25.1.1.0) on the top.
Solution 4.2
Separate OID at the base.
static final OID sysDescr1 = new OID("1.3.6.1.4.1.5.6.1.8.9"),
sysDescr2 = new OID("1.3.6.1.4.1.5.6.2.2.5");
Fix the database OIDs to get separate contextScopes.
In addition
You can try reading SNMP4J-Agent-Instrumentation-Guide.pdf. This didn't helped me btw.
You can attach the sources to your IDE to read about zero trailer and other nuances. This helped me a lot to get more info about DefaultMOServer.
Correct pom.xml import to get latest version
<repositories>
<repository>
<id>SNMP4J</id>
<url>https://oosnmp.net/dist/release/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j-agent</artifactId>
<version>2.3.2</version>
</dependency>
</dependencies>
First of all, OIDs do start with a number - not a dot. The syntax you are using is from NET-SNMP and is non-standard.
Second, please read the SNMP4J-Agent-Instrumentation-Guide.pdf document that describes in detail how you can instrument an agent for a MIB. You got the duplicate registration exception, because you registered a scalar as a sub-tree. Scalar OIDs have to end with the ".0" instance suffix.
Using the CommandResponder interface is sort of reinventing the wheel. You will most likely never manage to implement a secure and standard conform SNMP agent when you start from scratch. Using SNMP4J-Agent and its instrumentation hooks will save you a lot of work and trouble.
At first I misunderstood my problem and posted this question : Can someone explain me Cascading and FetchType lazy in Ektorp?
What I need to do: I need to save an Entity in couchdb and then have way to read it and potentially ignore some fields.
So I came up with this solution: I create a show function that delete fields from an object and then send it back.
function(doc, req) {
var result = doc;
var ignore = JSON.parse(decodeURIComponent(req.query.ignore)); //this is an array of field names
for (var i = 0, j = ignore.length; i < j; i++) {
if (result[ignore[i]]) {
delete result[ignore[i]];
}
}
return {
body : JSON.stringify(result),
headers : {
"Content-Type" : "application/json"
}
};
}
I have the same function but reversed in which the object keeps the fields I tell the function to keep.
Is there a better way to do this?
I also want to use Ektorp to call this but it allows me to only call Views. Right now I am forced to manage the http request myself. Is there a way to avoid this?
Right now this is the code I must use, but I would like to use Ektorp to do this.
HttpClient httpClient = new StdHttpClient.Builder().url("http://localhost:5984").build();
CouchDbInstance dbInstance = new StdCouchDbInstance(httpClient);
CouchDbConnector db = new StdCouchDbConnector("mydatabase", dbInstance);
db.createDatabaseIfNotExists();
String[] forget = new String[] { "field_to_ignore" };
String uri = "/mydatabase/_design/mydesigndoc/_show/ignorefields/mydocid?ignore=" + URLEncoder.encode(Json.stringify(Json.toJson(forget)), "UTF-8");
System.out.println(uri);
HttpResponse r = db.getConnection().get(uri);
String stuff = new Scanner(r.getContent()).useDelimiter("\\A").next();
System.out.println(stuff);
A show function isn't a terrible idea, from a CouchDB point of view. Ektorp may not support them, presumably because they're not hugely used, but Ektorp's open-source and on Github; you could easily just add this functionality, especially since you already have the basics of a working implementation of it.
Alternatively you could just build a view that does this for a given set of fields. You can't really parameterize this though, so you'd need well-defined sets of fields you know beforehand.
Finally I'd suggest either pulling the whole document and not worrying about it (unless you're in an extremely hugely bandwidth-limited situation it's probably not going to matter), or splitting the document into the constituent parts you're querying for and requesting them independently, if that's definitely the unusual case.
To expand my question, you could say that I want to program in SmartGWT instead of programming into SmartGWT ( http://msmvps.com/blogs/jon_skeet/archive/2008/04/23/programming-quot-in-quot-a-language-vs-programming-quot-into-quot-a-language.aspx ).
I have a 2 column ListGrid, populated with data from the 5 column database table. I don't use a DataSource (more on that later), instead I get the data from the async service and populate it on success like this predmetiGrid.setData(PredmetRecord.convertToContractRecordArray(result)); . The user can edit the data and press the Save button to save it. The way I have implemented the save is:
// repeat this for each edited field
for (int i=0; i < predmetiGrid.getAllEditRows().length; i++){
int editedRowIndex = predmetiGrid.getAllEditRows()[i];
// for each edite get the full record
PredmetRecord editedRecord = (PredmetRecord)predmetiGrid.getRecord(editedRowIndex);
// create a new DomainObject - Predmet, and set the ID from the
// Row so I have the ID to use for update later
Integer predmetID = editedRecord.getAttributeAsInt("predmetID");
Predmet predmet = new Predmet(predmetID);
// fill Predmet object with either the edited value, or the
// original value (if only one of the fields was changed and not both)
String editedNazivPredmeta = (String)predmetiGrid.getEditValues(editedRecord).get("nazivPredmeta");
boolean isNazivChanged = editedNazivPredmeta != null;
if (!isNazivChanged){
editedNazivPredmeta = editedRecord.getAttribute("nazivPredmeta");
}
predmet.setNazivPredmeta(editedNazivPredmeta);
String editedOpisPredmeta = (String) predmetiGrid.getEditValues(editedRecord).get("opisPredmeta");
boolean isOpisChanged = editedOpisPredmeta != null;
if (!isOpisChanged){
editedOpisPredmeta = editedRecord.getAttribute("opisPredmeta");
}
predmet.setOpisPredmeta(editedOpisPredmeta);
predmetiList.add(predmet);
}
In another method I call the async service:
public void updatePredmeti(List<Predmet> predmeti) throws RpcException, IllegalArgumentException {
for (int i=0; i<predmeti.size();i++){
JdbcPredgledPredmetaDAO.getInstance().updatePredmet(predmeti.get(i));
}
}
Now there are a few problems with this implementation. The most obvious ones are:
a) I'm not using a Datasource conected with the ListGrid. I don't use it because I don't understand how to use it in my case since the examples are written either for an XML DataSource or for the SmartGWT Pro (or higher) integrated server.
b) The async method needs to have a rollback mechanism if one of the inserts fail, though there could be a smarter implementation of this (e.g. do all inserts in one transaction).
c) I'm "hacking" to get and update the data instead of using object methods/properties but this is, currently, the best I got form the JavaDoc; I'd prefer to see best practice way to write this and learn
I'm using SmartGWT LGPL 3.0, Tomcat 7.0, Java 1.6
You can use a custom Datasource. DataSource.setDataFormat(DSDataFormat.CUSTOM). With this setting the DataSource will not handle the response, instead you have to parse it with transformResponse().
I am using a local database in my version of Lotus notes(8.5.2), and I am trying to get the data for two things:
The highlighted document/item in a NotesUIView
The document selected in a NotesUIDocument
However, all I get are the Notes URLs and I don't know what I should do with those. Can anyone help me out/throw me a breadcrumb?
P.S. Yes I am using the Java API for Eclipse.
Here is a code sample of what I do:
NotesUIWorkspace workSpace = new NotesUIWorkspace();
NotesUIElement currentElement = workSpace.getCurrentElement();
if (currentElement instanceof NotesUIView) {
NotesUIView currentView = (NotesUIView) currentElement;
NotesUIViewEntryCollection collection = currentView
.getActionableEntries();
Iterator docIterator = collection.documentIterator();
while (docIterator.hasNext()) {
NotesUIDocumentEntry entry = (NotesUIDocumentEntry) docIterator.next();
//I can't seem to get to the NoesUIDocument case like I can below... I want fields!
}
}
if(currentElement instanceof NotesUIDocument){
NotesUIDocument document = (NotesUIDocument) currentElement;
//Seem to be able to get the correct data fields only in this case!
document.getFields();
}
Fetching the "current" document is usually done via the NotesAgentContext.UnprocessedDocuments. In a view, that might return a collection of documents if the user as ticked several.
If you already have an NotesUIView, NotesUIView.getActionableEntries will give you the selected document(s).
When you have a NotesDocumentData instance, NotesUIWorkspace.openDocument can be used to open it up in edit mode. Then NotesUIWorkspace.getCurrentDocument can be used to get hold of the UI Document.
Notice that if you only want to read values from the document, it is more convenient to use the back-end classes like Document.
Have you got a URL as an example? If it includes the UUID of the document in question then you should be able to reference it directly with a getDocument(). Otherwise, the URL should include a view reference and a lookup key for that view in question.