How to add itemType facet for hybris OCC - facet

I want to be able to use the itemtype you can use in backoffice (image attach) in the rest api like this "https://localhost:9002/rest/v2/test/products/search?fields=FULL&query=:name-asc:itemType:Concrete:category:PHX";
is that possible?
im using hybris 6.4

It is possible. You have to create indexed property for your SOLR configuration which indexes item type.
For that create impex:
INSERT_UPDATE SolrIndexedProperty; $solrIndexedType; name[unique = true] ; backofficeDisplayName; type(code); facet[default=true]; multiValue; priority; fieldValueProvider ; valueProviderParameter ; facetDisplayNameProvider ; facetType(code); facetSort(code); visible[default=true]
; ; productType ; Product Type ; string ; ; false ; 1 ; productTypeValueResolver ; ; ; MultiSelectOr ; Alpha
And then create your resolver
public class ProductTypeValueResolver extends AbstractValueResolver<ItemModel, Object, Object> {
#Override
protected void addFieldValues(final InputDocument inputDocument, final IndexerBatchContext indexerBatchContext,
final IndexedProperty indexedProperty, final ItemModel product,
final ValueResolverContext<Object, Object> resolverContext) throws FieldValueProviderException {
inputDocument.addField(indexedProperty, product.getItemtype(), resolverContext.getFieldQualifier());
}
}
and finally create a spring bean with that resolver
<bean id="productTypeValueResolver" class="com.your.package.ProductTypeValueResolver" parent="abstractValueResolver">
After that you will get extra property in solr which will reflect your item type and you can use it on product search endpoint

Related

Ignite SqlQuery for complex java objects

In my cache I have a complex java object as below -
class Person{
private Department d;
....
}
class Department {
private Department code;
....
}
I am using below SQLQuery to read it -
SqlQuery<Short, BinaryObject> query = new SqlQuery<>(Person.class, "d.code = ?");
String args="101"; // department code
QueryCursor<Cache.Entry<Short, BinaryObject>> resultSet = personCache.query(query.setArgs(args))
I am getting below error -
Caused by: class org.apache.ignite.internal.processors.query.IgniteSQLException: Failed to parse query: SELECT "PERSON_CACHE"."PERSONENTITY"._KEY, "TPERSON_CACHE"."PERSONENTITY"._VAL FROM "PERSON_CACHE"."PERSONENTITY" WHERE id.code = ?
Am I doing anything wrong here ?
You can access nested fields, but only if they were configured with QuerySqlField annotation in advance:
class Person{
private Department d;
...
}
class Department {
#QuerySqlField
private Department code;
....
}
SqlQuery<Short, BinaryObject> query = new SqlQuery<>(Person.class, "code = ?");
Destructuring is not supported by Ignite SQL and there are no solid plans to implement it.
This means you can't peek into fields that are rich objects, maps, lists, etc. You should introduce a departmentId numeric field here.
Theoretically you could also try putting #QuerySqlField annotation on Department's field code, and then access it as CODE = ?. Your mileage may vary. I for one would like to hear about the result of such experiment.
I resolved it by using predicate.
IgniteBiPredicate<Long, BinaryObject> predicate = new IgniteBiPredicate<Long, BinaryObject>() {
#Override
public boolean apply(Long e1, BinaryObject e2) {
Person p= e2.deserialize();
short s = (short) args[0];
return p.getId().getCode == s;
}
};

Renaming of cross references not happening if the cross references are cached

I have a sample model i am using as below
grammar org.xtext.example.testdsl.TestDsl with org.eclipse.xtext.common.Terminals
generate testDsl "http://www.xtext.com/test/example/TestDsl"
Model:
prog+=Program*;
Program: g=Greeting de+=DataEntry* s+=Statement*;
Greeting: 'Hello' t=ProgPara '!';
ProgPara: 'PROGRAM' pname=Progname ';';
Progname : name=ID;
DataEntry: a=INT (v=Varname| in=Indexname) ';';
Varname : name = ID;
Statement: c=CopyStmt ';';
CopyStmt: 'COPY' 'TO' qname=[IndexVarname|ID] ;
IndexVarname : (Indexname|Varname);
Indexname : '(' name = ID ')';
Named:Progname|Indexname|Varname;
I have added caching support for Scoping like in the code below:
class TestDslScopeProvider extends AbstractTestDslScopeProvider {
#Inject
IResourceScopeCache cache;
override getScope(EObject context, EReference reference) {
if (context instanceof CopyStmt) {
if (reference.featureID == TestDslPackage.COPY_STMT__QNAME) {
val candidates = cache.get(
"COPY_STMT__QNAME_scope",
reference.eResource,
[|findQNameCandidates(context, reference)]
);
return Scopes.scopeFor(candidates);
}
}
return super.getScope(context, reference);
}
def findQNameCandidates(EObject context, EReference reference) {
val rootElement = EcoreUtil2.getRootContainer(context);
val candidates1 = EcoreUtil2.getAllContentsOfType(rootElement, IndexVarname);
return candidates1;
}
}
Now i have a sample test case as below:
Hello PROGRAM test;!
1 test1;
2 (test4);
3 test3;
COPY TO test4;
COPY TO test4;
When i try to rename test4 using the Rename Element, only the variable in the definition is getting renamed. The references are not getting renamed. Without caching it works fine, but when caching is done, i hit this issue. What am i missing here?
Thanks,
Anitha
you do cache wrong
reference.eResource
you need to use the context resource as cache not the metamodels
context.eResource,

Using OWL API, how to get class or individual name

I can get OWLClass and access the information. The classes and individuals are along with prefix.
Is there any method to get rid of prefix?
For example:
OWLClass cls = factory.getOWLClass(":Person", pm);
for (OWLIndividual indiv : cls.getIndividuals(onto)) {
System.out.println(indiv.toString());
}
print:
<http://www.co-ode.org/ontologies/ont.owl#Mon>
<http://www.co-ode.org/ontologies/ont.owl#Dad>
What I want is just Mon Dad
UPDATE:
Thank you Ignazio.
I found that the key is getIRI() method.
for (OWLIndividual indiv : owlclass.getIndividuals(onto)) {
System.out.println(indiv.asOWLNamedIndividual().getIRI().getFragment());
}
for (OWLClassExpression expre : owlclass.getSubClasses(onto)) {
System.out.println(expre.asOWLClass().getIRI().getFragment());
}
For entities, you can do this with OWLEntity.getIRI().getFragment().
Note however that not all entities have a name of this kind, as an Iri can legitimately end with / or #
A little update : getFragment() is deprecated now. I use getShortForm() instead.
I have faced the same problem and used OWLEntity.getIRI().getShortForm().
I retrieved class names into a List as follows
get ontology from the disk and assign to variable o Type ;
OWLOntology o;
And Created list to add Classes as follows
List listofClass = new ArrayList();
Then add the following codes
Collection<OWLClass> classes = o.getClassesInSignature();
//getting class names in the ontology
for (OWLClass owlClass : classes) {
System.out.println(owlClass.getIRI().getShortForm());
listofClass.add(owlClass.getIRI().getShortForm());
}
return listofClass;
}

HibernateException: Errors in named query

When running a particular unit-test, I am getting the exception:
Caused by: org.hibernate.HibernateException: Errors in named queries: UPDATE_NEXT_FIRE_TIME
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:437)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1385)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:891)
... 44 more
for the named query defined here:
#Entity(name="fireTime")
#Table(name="qrtz_triggers")
#NamedQueries({
#NamedQuery(
name="UPDATE_NEXT_FIRE_TIME",
query= "update fireTime t set t.next_fire_time = :epochTime where t.trigger_name = 'CalculationTrigger'")
})
public class JpaFireTimeUpdaterImpl implements FireTimeUpdater {
#Id
#Column(name="next_fire_time", insertable=true, updatable=true)
private long epochTime;
public JpaFireTimeUpdaterImpl() {}
public JpaFireTimeUpdaterImpl(final long epochTime) {
this.epochTime = epochTime;
}
#Override
public long getEpochTime() {
return this.epochTime;
}
public void setEpochTime(final long epochTime) {
this.epochTime = epochTime;
}
}
After debugging as deep as I could, I've found that the exception occurs in w.statement(hqlAst) in QueryTranslatorImpl:
private HqlSqlWalker analyze(HqlParser parser, String collectionRole) throws QueryException, RecognitionException {
HqlSqlWalker w = new HqlSqlWalker( this, factory, parser, tokenReplacements, collectionRole );
AST hqlAst = parser.getAST();
// Transform the tree.
w.statement( hqlAst );
if ( AST_LOG.isDebugEnabled() ) {
ASTPrinter printer = new ASTPrinter( SqlTokenTypes.class );
AST_LOG.debug( printer.showAsString( w.getAST(), "--- SQL AST ---" ) );
}
w.getParseErrorHandler().throwQueryException();
return w;
}
Is there something wrong with my query or annotations?
NamedQuery should be written with JPQL, but query seems to mix both names of persistent attributes and names of database columns. Names of database columns cannot be used in JPQL.
In this case instead of next_fire_time name of the persistent attribute epochTime should be used. Also trigger_name looks more like name of the database column than name of the persistent attribute, but it seems not to be mapped in your current class at all. After it is mapped, query is as follows:
update fireTime t set t.epochTime = :epochTime
where t.triggerName = 'CalculationTrigger'
If SQL query is preferred, then #NamedNativeQuery should be used instead.
As a side note, JPA 2.0 specification doesn't encourage changing primary key:
The application must not change the value of the primary key[10]. The
behavior is undefined if this occurs.[11]
In general entities are not aware of changed made via JPQL queries. That gets especially interesting when trying to refresh entity that does not exist anymore (because primary key was changed).
Additionally naming is little bit confusing:
Name of the class looks more like name of the service class
than name of the entity.
Starting name of the entity with lower
case letter is rather rare style.
Name of the entity, name of the
table and name of the class do not match too well.

Get name of the parsed file?

I would like to parse a file where the first line may or may not contain a definition of a "project" name (like with Pascal's program keyword), and if not, use the name of the file that is being parsed as default. Simplified:
#members{ String projectName; }
project : {projectName = ...} // name of parsed file as default
( PROJECTNAMEKEYWORD ID {projectName = $ID.text;} )?
otherstuff {/*...*/};
Is this even possible? I found this surprisingly hard to find out using google or the antlr manual. By its documentation, input.getSourceName() should be what I am looking for, but it always returns null, and debugging lead me to the class ANTLRStringStream that has a name field whose value is returned by this method but never set.
Simply create a custom constructor in your parser that takes a string that represents your file.
A demo:
grammar T;
#parser::members {
private String projectName;
public TParser(String fileName) throws java.io.IOException {
super(new CommonTokenStream(new TLexer(new ANTLRFileStream(fileName))));
projectName = fileName;
}
public String getProjectName() {
return projectName;
}
}
parse
: (PROJECT ID {projectName = $ID.text;})? EOF
;
PROJECT : 'project';
ID : ('a'..'z' | 'A'..'Z')+;
SPACE : (' ' | '\t' | '\r' | '\n') {skip();};
which can be tested with:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
// 'empty.txt' is, as the name suggests, an empty file
TParser parser = new TParser("empty.txt");
parser.parse();
System.out.println(parser.getProjectName());
// 'test.txt' contains a single line with the words: 'project JustATest'
parser = new TParser("test.txt");
parser.parse();
System.out.println(parser.getProjectName());
}
}
If you run the Main class, the following will be printed to your console:
empty.txt
JustATest