Batch assigning attributes of a category
Hi,
I have a list of object ids all of which are tagged using the same category.
I now want to assign a certain attribute value of a Text: Popup (drop down) field to all of those object ids.
Any idea/hint how to do that with OScript?
Thanks a lot
Juergen
Comments
-
the attrdata data structure is the commonly used one.The psuedo code follows this
With Each Objectid
ask NodeCategoriesGet
Isolate the category you want manipulated
change the values using the attribute display name key method
dbput to save changes
end with
repeat for other objectid's
https://knowledge.opentext.com/knowledge/cs.dll?func=ll&objId=20007573&objAction=viewincontainer
There is another way that I found out when reseraching something but I am not able to rememebr that correctly now.It was a tad bit more easy once you understand it.
attched is a utility script I created so that given a dataid and a category name and the values one could manipulate it.I put that as a utils script you can look at its implementation if that helps
https://knowledge.opentext.com/knowledge/cs.dll?func=ll&objId=17996016&objAction=download&viewType=1
I used the simple OT code I found on the KB for different types of categories not completely checked or thorough by any means
0 -
Thanks a lot for your post! It helped big style to adopt it to my needs, I attach the first version of the code to this post, perhaps it helps someone.
Juergen
---8<---</p>
/* description *//*This script loads a list of object ids from a text fileand adds a Text Popup attribute entry of a given category*//* configuration data */Assoc aChangeDataaChangeData.( 'sCategory' ) = "[name of category]"aChangeData.( 'sAttribute' ) = "[name of attribute]"aChangeData.( 'sAttributeValue' ) = "[new value for dropdown list]"String pathRoot = "p:/ath/"String fileInput = pathRoot + "input.txt"String fileError = pathRoot + "error.log"String fileSuccess = pathRoot + "success.log"/* code */File hdInput = File.Open( fileInput, File.ReadMode )File hdError = File.Open( fileError, File.WriteMode )File hdSuccess = File.Open( fileSuccess, File.WriteMode )String s = ""Integer nidAssoc rvif ( ! IsError( hdInput ) ) // OT construct to loop through input file for ( s = File.Read( hdInput ); s != File.E_Eof; s = File.Read( hdInput ) ) nid = Str.StringToInteger( s ) if( isDefined( nid ) ) // call routine to change attribute value rv = setAttributeForObjectId( this.fprgCtx, nid, aChangeData ) else rv.OK = FALSE rv.errMsg = s + " is no valid object id format." end // log result if( rv.OK ) File.Write( hdSuccess, Str.ValueToString( nid ) ) else File.Write( hdError, rv.errMsg ) end end File.Close( hdInput ) File.Close( hdError ) File.Close( hdSuccess )end// check if a value exists in listfunction Boolean bHasValue( List lsValues, String sValue ) Integer c = Length( lsValues ) Integer ix String s for ix = 1 to c s = lsValues[ ix ] if( s == sValue ) return true end end return falseendfunction Assoc setAttributeForObjectId( Object prgCtx, Integer nid, Assoc aChangeData ) Dynamic result Dynamic aCategoryData List llsCategories Boolean found, bFoundAttribute List lsCategories Integer ixCategory = 0 Integer nidAttribute Dynamic category,aAttributes List lsUpdatedItems String sCategory = aChangeData.( 'sCategory' ) String sAttributeValue = aChangeData.( 'sAttributeValue' ) String sAttribute = aChangeData.( 'sAttribute' ) String sid = Str.ValueToString( nid ) Assoc retVal retVal.OK=TRUE retVal.errMsg="" //Get the keys of the assoc Dynamic docNode = DAPI.GetNodeById(prgCtx.DSession().fSession, DAPI.BY_DATAID, nid) if isError(docNode) retVal.OK = FALSE retVal.errMsg = sid + " is no valid node" return retVal end // Create a new attrData structure to return the info in aCategoryData = $LLIApi.attrData.New( prgCtx, nid, docNode.pVersionNum ) // Get the data from the database for this object (All categories) result = aCategoryData.DBGet() if !result.OK retVal.OK = FALSE retVal.errMsg = sid + " has no categories attached" return retVal end if result.OK // Now get the list of all categories attached llsCategories = aCategoryData.AttrGroupNameList() // We now must look for the category specified to see if it was returned found = false bFoundAttribute = false for lsCategories in llsCategories If lsCategories[ 2 ] == sCategory // The category specified was found. found = true Integer ixCategory = 0 // Now we need to extract the id of the category for category in aCategoryData.fDefinitions ixCategory = ixCategory + 1 if category.DisplayName == sCategory // ixCategory now holds id of target category // now lets look at the target attribute for aAttributes in aCategoryData.fDefinitions[ixCategory].Children if aAttributes.DisplayName == sAttribute bFoundAttribute = true // now we are in the target attribute, lets get its id nidAttribute = aAttributes.ID // get valid values for this attribute List lsValidValues = aAttributes.ValidValues // if new attribute value is valid update the data object accordingly if( bHasValue( lsValidValues, sAttributeValue ) ) List lsItems = aCategoryData.fData[ixCategory].Values[1].(nidAttribute).Values Integer cItems = Length( lsItems ) if( cItems == 1 && IsUndefined( lsItems[ 1 ] ) ) // no items set, set new one lsUpdatedItems = { sAttributeValue } else if( bHasValue( lsItems, sAttributeValue ) ) retVal.OK = FALSE retVal.errMsg = sid + " attribute value already exists" return retVal else // items already exist, add new one lsUpdatedItems = { @lsItems, sAttributeValue } end end // assign new attribute value to data object aCategoryData.fData[ixCategory].Values[1].(nidAttribute).Values = lsUpdatedItems else retVal.OK = FALSE retVal.errMsg = sid + " " + sAttributeValue + " is no valid value of attribute " + sAttribute return retVal end end end if( bFoundAttribute ) // Update node with new data object result = aCategoryData.DBPut() break else retVal.OK = FALSE retVal.errMsg = sid + " " + sAttribute + " is no attribute in category " + sCategory return retVal end end end if !result.OK retVal.OK = FALSE retVal.errMsg = sid + " updated failed, system says: " + result.APIError return retVal end end end if !found // the category is not in this node retVal.OK = FALSE retVal.errMsg = sid + " has no category called " + sCategory + " attached" return retVal end end return retValend
0 -
May I ask you an additional question? I got a request to correct a typo in a Text/Popup attribute value of a category.Now if I simply change the text value of the attribute in the category and apply that new version to my objects all previous assignments will be completely lost on those objects.Hence I was thinking of the following approach:* Fetch all object ids that are tagged with old attribute value (with typo) from LLATTRDATA table.* Add a new attribute value in (typo corrected) to attribute of category* Remove old attribute value (with typo) to attribute of category* Upgrade categories* Run above script to assign the new attribute valueIs there a more elegant way not including a category upgrade?Thanks,Juergen0
-
thank you for sharing this!
From: eLink Entry: Content Server Builder Forum [mailto:componentbuilder@elinkkc.opentext.com]
Sent: Thursday, March 29, 2012 3:59 AM
To: eLink Recipient
Subject: Batch assigning attributes of a categoryPosted byjuergen.riemer@osce.org (Riemer, Juergen) On 03-29-2012 03:53
Thanks a lot for your post! It helped big style to adopt it to my needs, I attach the first version of the code to this post, perhaps it helps someone.
Juergen
---8<---
/* description */
/*
This script loads a list of object ids from a text file
and adds a Text Popup attribute entry of a given category
*/
/* configuration data */
Assoc aChangeData
aChangeData.( 'sCategory' ) = "[name of category]"
aChangeData.( 'sAttribute' ) = "[name of attribute]"
aChangeData.( 'sAttributeValue' ) = "[new value for dropdown list]"
String pathRoot = "p:/ath/"
String fileInput = pathRoot + "input.txt"
String fileError = pathRoot + "error.log"
String fileSuccess = pathRoot + "success.log"
/* code */
File hdInput = File.Open( fileInput, File.ReadMode )
File hdError = File.Open( fileError, File.WriteMode )
File hdSuccess = File.Open( fileSuccess, File.WriteMode )
String s = ""
Integer nid
Assoc rv
if ( ! IsError( hdInput ) )
// OT construct to loop through input file
for ( s = File.Read( hdInput ); s != File.E_Eof; s = File.Read( hdInput ) )
nid = Str.StringToInteger( s )
if( isDefined( nid ) )
// call routine to change attribute value
rv = setAttributeForObjectId( this.fprgCtx, nid, aChangeData )
else
rv.OK = FALSE
rv.errMsg = s + " is no valid object id format."
end
// log result
if( rv.OK )
File.Write( hdSuccess, Str.ValueToString( nid ) )
else
File.Write( hdError, rv.errMsg )
end
end
File.Close( hdInput )
File.Close( hdError )
File.Close( hdSuccess )
end
// check if a value exists in list
function Boolean bHasValue( List lsValues, String sValue )
Integer c = Length( lsValues )
Integer ix
String s
for ix = 1 to c
s = lsValues[ ix ]
if( s == sValue )
return true
end
end
return false
end
function Assoc setAttributeForObjectId( Object prgCtx, Integer nid, Assoc aChangeData )
Dynamic result
Dynamic aCategoryData
List llsCategories
Boolean found, bFoundAttribute
List lsCategories
Integer ixCategory = 0
Integer nidAttribute
Dynamic category,aAttributes
List lsUpdatedItems
String sCategory = aChangeData.( 'sCategory' )
String sAttributeValue = aChangeData.( 'sAttributeValue' )
String sAttribute = aChangeData.( 'sAttribute' )
String sid = Str.ValueToString( nid )
Assoc retVal
retVal.OK=TRUE
retVal.errMsg=""
//Get the keys of the assoc
Dynamic docNode = DAPI.GetNodeById(prgCtx.DSession().fSession, DAPI.BY_DATAID, nid)
if isError(docNode)
retVal.OK = FALSE
retVal.errMsg = sid + " is no valid node"
return retVal
end
// Create a new attrData structure to return the info in
aCategoryData = $LLIApi.attrData.New( prgCtx, nid, docNode.pVersionNum )
// Get the data from the database for this object (All categories)
result = aCategoryData.DBGet()
if !result.OK
retVal.OK = FALSE
retVal.errMsg = sid + " has no categories attached"
return retVal
end
if result.OK
// Now get the list of all categories attached
llsCategories = aCategoryData.AttrGroupNameList()
// We now must look for the category specified to see if it was returned
found = false
bFoundAttribute = false
for lsCategories in llsCategories
If lsCategories[ 2 ] == sCategory
// The category specified was found.
found = true
Integer ixCategory = 0
// Now we need to extract the id of the category
for category in aCategoryData.fDefinitions
ixCategory = ixCategory + 1
if category.DisplayName == sCategory
// ixCategory now holds id of target category
// now lets look at the target attribute
for aAttributes in aCategoryData.fDefinitions[ixCategory].Children
if aAttributes.DisplayName == sAttribute
bFoundAttribute = true
// now we are in the target attribute, lets get its id
nidAttribute = aAttributes.ID
// get valid values for this attribute
List lsValidValues = aAttributes.ValidValues
// if new attribute value is valid update the data object accordingly
if( bHasValue( lsValidValues, sAttributeValue ) )
List lsItems = aCategoryData.fData[ixCategory].Values[1].(nidAttribute).Values
Integer cItems = Length( lsItems )
if( cItems == 1 && IsUndefined( lsItems[ 1 ] ) )
// no items set, set new one
lsUpdatedItems = { sAttributeValue }
else
if( bHasValue( lsItems, sAttributeValue ) )
retVal.OK = FALSE
retVal.errMsg = sid + " attribute value already exists"
return retVal
else
// items already exist, add new one
lsUpdatedItems = { @lsItems, sAttributeValue }
end
end
// assign new attribute value to data object
aCategoryData.fData[ixCategory].Values[1].(nidAttribute).Values = lsUpdatedItems
else
retVal.OK = FALSE
retVal.errMsg = sid + " " + sAttributeValue + " is no valid value of attribute " + sAttribute
return retVal
end
end
end
if( bFoundAttribute )
// Update node with new data object
result = aCategoryData.DBPut()
break
else
retVal.OK = FALSE
retVal.errMsg = sid + " " + sAttribute + " is no attribute in category " + sCategory
return retVal
end
end
end
if !result.OK
retVal.OK = FALSE
retVal.errMsg = sid + " updated failed, system says: " + result.APIError
return retVal
end
end
end
if !found
// the category is not in this node
retVal.OK = FALSE
retVal.errMsg = sid + " has no category called " + sCategory + " attached"
return retVal
end
end
return retVal
end
[To post a comment, use the normal reply function]
Topic:
Forum:
Content Server:
0 -
I think not...
For the existing objects with the typo if you change the value of the category:attribute data that would suffice.The minute you change the category version on the definition all those nodes sitting with old category data will demand/show that we all need to be upgraded right now.
In a similar situation where the doccontrollers changed the cat:att to include a mandatory value and gave me this requirement
1)Old category att data on nodes must be maintained
2)The node should be upgraded and a default value should be given to the new mandatory attribute that was given.OT Upgrade will skip those objects if it cannot find a mandatory value.Defining it at a folder level or the category definition will destroy all the old data in it. I was in a rich soup.
3)each node encountered had at least 3 more categories on it that needed to be maintained.
In the end I was able to accomodate the needs with my own implementation of a "nodecrawler" .
Further my peeking in the oscript layer made me understand that llattrblobdata was the real deal and llattrdata was reconstructed based on that.
Hopefully in this age of webreports something of the same could be acheived albeit using their tag programming.oscript is going to be faster as you reach the engine directly.
0 -
Hi Appu,may I ask an additional question?I successfully run this script already; I always had to upgrade the categories afterwards for another reason which was great because without the upgrade of the entire category the items were properly tagged with the new attribute value, however, you couldn't search for them. Only the category upgrade "re-indexed" them.I'd like to decouple this.What I IMHO need to do is to run the "upgrade category" function on all of those object ids. Do you have a hint which methods to call to perform a category upgrade for a single object id?Thanks so much,Juergen0
-
You only need to do this
Assoc myResult=attrData.Upgrade(myDefID)(see the attrdata class method)
However
The upgrade category is a single function but it does not work if the data is not put right.
I can tell you with an e.g Assume a category with this spec {12345,5} is applied to some nodes
of your livelink.For simplicity's sake I will say that there are 40 folders and 60 documents with this data.
Assume you now changed the category so it is now {12345,6} and added a mandatory value.
If you try to upgrade the said Id's 40 will get upgraded and 60 will get rejected saying it needs a mandatory value filled.If you hardcode the manadatory value it will work but it will replace the existing values of the original attributes i don't think it will "merge".Are there ways around it Yes very contrived
- On a livelink server where your code is running take out the mandatoriness insistence of categories which is what you do by going "System Administration->Configure Attribute Value Requirements'.This is the flag that makes documents insist on mandatory and so on.After you upgrade you can put it back.This idea did not fly with my customer when I was developing.I am not sure if this setting is a per instance setting or in KINI if it is in KINI then all your instances will behave like this.
Attached is a utilty script from my program it will not work as such but as you can see when I sense that I can't upgrade a category unless I fill in the manadatory value...
https://knowledge.opentext.com/knowledge/cs.dll?func=ll&objaction=overview&objid=24681779
0 -
Hi Appu,
Thanks a lot for your detailed information! I will have a look at your code, great!
Juergen
0
Categories
- All Categories
- 108 Developer Announcements
- 53 Articles
- 106 General Questions
- 145 IM Services
- 43 OpenText Hackathon
- 32 Developer Tools
- 20.6K Analytics
- 4.1K AppWorks
- 8.9K Extended ECM
- 899 Cloud Fax and Notifications
- 77 Digital Asset Management
- 9.3K Documentum
- 29 eDOCS
- 120 Exstream
- 39.8K TeamSite
- 1.7K Web Experience Management