How to fetch local attribute value through QuerySpec in Windchill - ptc-windchill

I created a local string type attribute on a type in Windchill. I'm trying to fetch the value of that attribute using QuerySpec but it's throwing the following exception:
2019-04-16 20:53:05,092 INFO [ajp-nio-127.0.0.1-8011-exec-5]
wt.system.err - wt.query.QueryException: Attribute
"ptc_str_89typeInfoLCSProduct" is not a member of class "class
com.lcs.wc.product.LCSSKU" 2019-04-16 20:53:05,092 INFO
[ajp-nio-127.0.0.1-8011-exec-5] wt.system.err - Nested exception is:
Attribute "ptc_str_89typeInfoLCSProduct" is not a member of class
"class com.lcs.wc.produ
Following is my code:
String colorwayId = product.getFlexType().getAttribute("colorwayID")
.getColumnName();
QuerySpec qs = new QuerySpec();
int classIndex = qs.appendClassList(typeDefRef.getKey().getClass(), false);
ClassAttribute ca = new ClassAttribute(
typeDefRef.getKey().getClass(), colorwayId);
qs.appendSelect(ca, new int[] { classIndex }, false);
QueryResult qr = PersistenceHelper.manager.find(qs);

Normally ClassAttribute gets attribute name instead of column name (database column).
Your ptc_str_89typeInfoLCSProduct column is in fact typeInfoLCSProduct.ptc_str_89 like State is state.state.
To get this information, you need to use PersistableAdapter like this:
public String getAttributeColumnName(String softType, String logicalAttributeName) throws WTException {
PersistableAdapter persistableAdapter = new PersistableAdapter(softType, Locale.getDefault(), Operation.DISPLAY);
persistableAdapter.load(logicalAttributeName);
AttributeTypeSummary attributeDescriptor = persistableAdapter.getAttributeDescriptor(logicalAttributeName);
return null != attributeDescriptor ? (String) attributeDescriptor.get(AttributeTypeSummary.DESCRIPTION) : null;
}
And then use this method:
String colorwayId = getAttributeColumnName("your_softtype", "attribute_name_from_type_manager");

Related

How to deal with Firestore returning null values in Map

I'm making an app using Flutter/Dart and have run into an annoying issue.
When I want to add another variable to an object, such as the FoodItem object in this example, and I need to parse the snapshot data into the dart object, the map Firestore returns usually doesn't contain the new value and ends up telling the new object to just make the new variable null.
This causes problems throughout the app. How should I approach this without null checking for every single element being parsed? Thanks!
class FoodItem with ChangeNotifier {
String name;
String barcode;
String servingSize;
String calories;
String totalFat;
String satFat;
String transFat;
String cholesterol;
String sodium;
String totalCarbs;
String protein;
String fiber;
String sugar;
bool new_variable_that_ends_up_null = false;
...
FoodItem.fromSnapshotData(Map<String, dynamic> data)
: name = data['Name'],
calories = data['Calories'],
barcode = data['Barcode'],
servingSize = data['Serving Size'],
totalFat = data['Total Fat'],
satFat = data['Saturated Fat'],
transFat = data['Trans Fat'],
cholesterol = data['Cholesterol'],
sodium = data['Sodium'],
totalCarbs = data['Total Carbs'],
fiber = data['Fiber'],
sugar = data['Sugar'],
protein = data['Protein'],
new_variable_that_ends_up_null = data['New Variable']; // This will return null when it's not already in firstore.
}
try this out :
new_variable_that_ends_up_null = data['New Variable'] ?? false
problem here is u cannot assign null to the bool it will give u error

Entity Framework 6 .add() with variable table and column name

I am able to get a somewhat dynamic Entity Framework search result with the following simplified example, which pulls a single result from the DB or Cache:
string strTableName = "TableName2"
string strColumnName = "MyColumnName"
int intPrimaryKey = 1
Type returnType;
returnType = typeof(TableName1);
string queryResults = null;
switch (strTableName)
{
case "TableName2":
returnType = typeof(TableName2);
break;
}
var refColumnName = returnType.GetProperty(strColumnName );
var query = mydbEntity.Set(returnType).Find(intPrimaryKey );
var queryResults = refColumnName.GetValue(query).ToString();
This can also be adapted for Updating a record:
DataQuery.LeadsEntity.Entry(query).Property(strColumnName ).CurrentValue = "Whatever";
DataQuery.LeadsEntity.SaveChanges();
Is there an equivalent for way for .set(returnType).Add()? I'm not sure if there is a way to do this type of thinking using variable table and column names:
DataQuery.LeadsEntity.Set(returnType).Add(new returnType { PrimayKeyName = 1, refColumnName = "Something" });
If you don't know a priori what's the name of the primary key property, it could be a little painful to get it from the type.
This is the way I found more reliable to retrieve the primary key from the entity type:
private string[] GetKeyNames(DbContext context, Type entityType)
{
ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;
//create method CreateObjectSet with the generic parameter of the base-type
MethodInfo method = typeof(ObjectContext).GetMethod("CreateObjectSet", Type.EmptyTypes)
.MakeGenericMethod(entityType);
dynamic objectSet = method.Invoke(objectContext, null);
IEnumerable<dynamic> keyMembers = objectSet.EntitySet.ElementType.KeyMembers;
string[] keyNames = keyMembers.Select(k => (string)k.Name).ToArray();
_keyNamesCache[entityType] = keyNames;
return keyNames;
}
But assuming your primary keys are always a single property, you could use reflection to create the entity object and set its properties like this:
private void CreateEntity(Type entityType, object pkValue, Dictionary<string, object> Columns)
{
// Create the new entity
var entity = Activator.CreateInstance(entityType);
// Get the primary key property name
var pkName = GetKeyNames(context, entityType).First();
// Set Pk value
entityType.GetProperty(pkName).SetValue(entity, pkValue);
// Set other column(s)
foreach (var col in Columns)
{
entityType.GetProperty(col.Key).SetValue(entity, col.Value);
}
// Add the entity to the DbSet
using (var context = new YourContext())
{
context.Set(entityType).Add(entity);
}
}

DeExpress MVC 17.1 How populate TokenBox from a database

I want populate a TokenBox from a database using the property tokenBoxSettings.Properties.DataSource
TokenBoxView.cshtml
groupSettings.Items.Add(
formLayoutSettings.Items.Add(i =>
{
i.FieldName = "email";
i.Caption = "Email";
i.NestedExtensionType = FormLayoutNestedExtensionItemType.TokenBox;
TokenBoxSettings tokenBoxSettings = (TokenBoxSettings) i.NestedExtensionSettings;
tokenBoxSettings.Width = 350;
//data binding
tokenBoxSettings.Properties.DataSource = mainController.GetMails();
tokenBoxSettings.Properties.TextField = "email_empresarial";
tokenBoxSettings.Properties.ValueField = "email_empresarial";
tokenBoxSettings.Properties.IncrementalFilteringMode = IncrementalFilteringMode.Contains;
tokenBoxSettings.Properties.ValueSeparator = ';';
})
);
TokenBoxController.cs
//mainController
//I created a dictionary based on the result of select
public Dictionary<string, string> GetMails()
{
var email = db.usuario.ToList().Select(e => new { e.email_empresarial });
var emails = new Dictionary<string, string>();
foreach (var mail in email)
{
correos.Add(mail.ToString(), mail.ToString());
}
return emails;
}
But it shows me the "object explicitly", I only need the value, for example kenneth or manuel
tokenBox list
What am I doing wrong? or with what other approach I can do?
You are specifying same email_empresarial field name for both tokenBoxSettings.Properties.TextField and tokenBoxSettings.Properties.ValueField.
Since you are binding your TokenBox to Dictionary, try changing settings for TextField and ValueField to reference Dictionary Key and Value, like this:
tokenBoxSettings.Properties.TextField = "Value";
tokenBoxSettings.Properties.ValueField = "Key";
Also, in your GetMail() method you have declared the var emails but in the loop you are adding items to the undeclared correos variable. Are you sure you don't have a bug here?
Another note, in the Dictionary returned by GetMails() you populate both dictionary keys and values with the same value of mail.ToString(). Are you sure you really need to use Dictionary to bind your TokenBox? If keys and values are equal you may try going with plain List<string>.

Why does Spring LDAP's LdapTemplate not return title, department & company attributes?

I'm using spring-ldap-core-2.3.1.RELEASE.jar over JDK 1.8 & Tomcat 8.0 to access AD information through LdapTemplate. The attributes such as title,department & company are not being returned by the ldapTemplate.search(..,.,..) method.
I'm using the following lines of code to search :-
LdapQuery ldapQuery = LdapQueryBuilder.query()
.where("objectclass").is("user")
.and("objectcategory").is("person")
.and("cn").like(strWildcardText+"*");
ldapTemplate.search(ldapQuery, new ADUserAttributesMapper());
Following is the ADUserAttributesMapper class :-
public class ADUserAttributesMapper implements AttributesMapper<ADUserBean> {
#Override
public ADUserBean mapFromAttributes(Attributes attributes) throws NamingException {
if(attributes==null) {
return null;
}
adUserBean.setName((attributes.get("name")!=null) ? attributes.get("name").get().toString() : null);
adUserBean.setCommonName((attributes.get("cn")!=null) ? attributes.get("cn").get().toString() : null);
adUserBean.setDisplayName((attributes.get("displayname")!=null) ? attributes.get("displayname").get().toString() : null);
adUserBean.setGivenName((attributes.get("givenname")!=null) ? attributes.get("givenname").get().toString() : null); // for FIRST NAME
adUserBean.setMiddleName((attributes.get("initials")!=null) ? attributes.get("initials").get().toString() : null); // for MIDDLE NAME / INITIALS
adUserBean.setLastName((attributes.get("sn")!=null) ? attributes.get("sn").get().toString() : null); // for LAST NAME
adUserBean.setDepartment((attributes.get("department")!=null) ? attributes.get("department").get().toString() : null);
adUserBean.setUserPrincipalName((attributes.get("userprincipalname")!=null) ? attributes.get("userprincipalname").get().toString() : null); // Logon Name
adUserBean.setsAMAccountName((attributes.get("samaccountname")!=null) ? attributes.get("samaccountname").get().toString() : null); // Logon Name (pre-Windows 2000)
adUserBean.setDistinguishedName((attributes.get("distinguishedname")!=null) ? attributes.get("distinguishedname").get().toString() : null);
adUserBean.setMailID((attributes.get("mail")!=null) ? attributes.get("mail").get().toString() : null);
adUserBean.setTitle((attributes.get("title")!=null) ? attributes.get("title").get().toString() : null); // Job Title
adUserBean.setTelephoneNumber((attributes.get("telephonenumber")!=null) ? attributes.get("telephonenumber").get().toString() : null);
adUserBean.setObjectCategory((attributes.get("objectcategory")!=null) ? attributes.get("objectcategory").get().toString() : null);
return adUserBean;
}
}
The title,department & company attributes belong to the Organization tab of the AD user properties as shown in the below image :-
Also, from the General tab the initials(initials) attribute is not being picked up/listed by Spring-LDAP's ldapTemplate. The LdapQueryBuilder.query() object has access to attributes(...) method that takes a string array of attribute names that are to be fetched. But even after mentioning them there explicitly, values for attributes such as initials, title, department & company are not returned.
The LDAP Browser plugin within the Eclipse IDE lists the title,department & company properties under the Organization tab without a problem.
Even the com4j API returns the title, department & company attributes.
Is there any configuration that is limiting the attribute(s) listing or is it a limitation with Spring-LDAP API itself? Are these attributes not part of BasicAttributes? How to fetch these attributes through Spring-LDAP?
UPDATE (01-Aug-2017):
The plain Java JNDI approach/code does NOT return department,company,title attributes (even with these attributes being explicitly mentioned in attributes string array), but surprisingly it does return the initials attribute value.
UPDATE (02-Aug-2017):
Similar to #Pierre's suggestion (below) tried the following code using SearchControls object :-
String strFilter= "(&(objectclass=top)(cn=cgma*))";
String[] attrs = new String[] {"cn","givenName","sn","initials","title","department","company"};
long maxResults = 10; // for example
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setReturningAttributes(attrs);
searchControls.setCountLimit(maxResults);
List<String> aLstOfADUsers = ldapTemplate.search("",strFilter,searchControls,new AttributesMapper<String>()
{
public String mapFromAttributes(Attributes attrs) throws NamingException {
try
{
System.out.println(attrs.toString());
return attrs.get("cn").get().toString();
}
catch(Exception ex) {
ex.printStackTrace();
return null;
}
}
});
return aLstOfADUsers;
Even this does not return the initials, title, company & department attribute values.
The person attributes might be internal attributes which you wouldn't get back by default. You can specify explicitly which attributes you want returned BUT not in the search method you're using (the one where you pass in an LdapQuery object). If you take a look at the org.springframework.ldap.core.LdapTemplate class, it doesn't seem like you can pass in the SearchControls object to the method signature you're using. So, to be able to specify attributes to fetch, replace this:
LdapQuery ldapQuery = LdapQueryBuilder.query()
.where("objectclass").is("user")
.and("objectcategory").is("person")
.and("cn").like(strWildcardText+"*");
ldapTemplate.search(ldapQuery, new ADUserAttributesMapper());
With this:
LikeFilter filter = new LikeFilter("cn", strWildcardText+"*");
// list of attributes to retrieve
String[] attrs = new String[] {"title","department","company"};
long maxResults = 10; // for example
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setReturningAttributes(attrs);
searchControls.setCountLimit(numResults);
ldapTemplate.search(DistinguishedName.EMPTY_PATH, filter.encode(), searchControls, new ADUserAttributesMapper());
The above should work. You could also try something like this (I haven't tried that yet):
ldapTemplate.search( "dc=yourorg,dc=com",
"(&(cn=" +strWildcardText + "*)(&(objectClass=person)(objectcategory=person)))",
SearchControls.SUBTREE_SCOPE,
new String[]{ "title","department","company" },
new ADUserAttributesMapper() );
Finally, to get ALL attributes back, ask to retrieve ALL attributes in the code above (my above example only asked for 3 attributes, this would return ALL of them):
String[] attrs = new String[]{"*","+"};
This is based on your AttributesMapper. I don't know what ADUserAttributesMapper is, so you'd have to provide that implementation.
Here's the javadoc for this interface. http://docs.spring.io/spring-ldap/docs/current/apidocs/org/springframework/ldap/core/AttributesMapper.html
Change ldap port from 3268 to 389

Why is java.lang.Long not persistable?

I am trying to query for a list of ids of type Long in GAE/JDO. And I'm getting the following exception when I call detachCopyAll() on the result set.
org.datanucleus.jdo.exceptions.ClassNotPersistenceCapableException: The class "The class "java.lang.Long" is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data/annotations for the class are not found." is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data for the class is not found.
at org.datanucleus.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:241)
at org.datanucleus.jdo.JDOPersistenceManager.jdoDetachCopy(JDOPersistenceManager.java:1110)
at org.datanucleus.jdo.JDOPersistenceManager.detachCopyAll(JDOPersistenceManager.java:1183)
...
I can query for a list of User objects and detach them just fine. I expected all primitive wrapper classes like Long to be persistable. What am I doing wrong? Below is the code I'm working with.
#PersistenceCapable(identityType=IdentityType.APPLICATION, detachable="true")
public class User
{
#PrimaryKey
#Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY)
private Long id;
private String email;
}
#SuppressWarnings("unchecked")
public static List<Long> getUserKeys(String email)
{
assert email != null;
List<Long> keyList = null;
PersistenceManager pm = null;
Query query = null;
try {
pm = PMF.get().getPersistenceManager();
query = pm.newQuery("select id from " + User.class.getName());
query.declareParameters("String emailParam");
query.setFilter("email == emailParam");
List<Long> resultList = (List<Long>) query.execute(email);
// next line causes the ClassNotPersistenceCapableException
keyList = (List<Long>) pm.detachCopyAll(resultList);
}
finally {
if (query != null) query.closeAll();
if (pm != null) pm.close();
}
return keyList;
}
List<Long> resultList = (List<Long>) query.execute(email);
// next line causes the ClassNotPersistenceCapableException
keyList = (List<Long>) pm.detachCopyAll(resultList);
I don't understand what you are doing here. A List<Long> does not have to be detached. You'd want to detach instances of your User entity class, but a Long is a Long, and you can just do whatever you need to do with the resultList.
The error message is confusing, but just caused by Long not being an entity class.

Resources