Alfresco Solr SearchService.query() error parsing Xpath - xpath

I'm trying to query for some files in Alfresco using SearchService; my idea is:
1) get folder's noderef where I want to search in for files
2) then get noderef's path via NodeService
3) finally query Solar via SearchService to find files in that specific path
The problem raises when querying to Solr, I get the following exception:
ERROR [solr.core.SolrCore] [http-bio-8443-exec-1] org.apache.solr.common.SolrException: org.apache.lucene.queryParser.ParseException: **Cannot parse** 'PATH:"/{http\://www.alfresco.org/model/application/1.0}company_home/{http\://www.alfresco.org/model/application/1.0}user_homes/{http\://www.alfresco.org/model/content/1.0}abeecher/{http\://www.alfresco.org/model/content/1.0}nominas//*"': **Failed to parse XPath**...
Unexpected '{http://www.alfresco.org/model/application/1.0}company_home/{http://www.alfresco.org/model/application/1.0}user_homes/{http://www.alfresco.org/model/content/1.0}abeecher/{http://www.alfresco.org/model/content/1.0}nominas//*'
If I replace the full prefixes by prefixes of type cm: etc... the query works well.
Is there any "Alfresco Way" to do this instead of transforming the string with a regex? Or am I doing something wrong?
Code I'm using is:
Path path3 = nodeService.getPath(folder);
SearchParameters sp = new SearchParameters();
sp.addStore(Repository.getStoreRef());
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
sp.setQuery("PATH:\"/{http://www.alfresco.org/model/application/1.0}company_home/{http://www.alfresco.org/model/application/1.0}user_homes/{http://www.alfresco.org/model/content/1.0}abeecher/{http://www.alfresco.org/model/content/1.0}nominas//*\"");
//sp.setQuery(path3);
//sp.setQuery(path3.toString());
ResultSet results = null;
results = searchService.query(sp);

afaik PATH-Queries using full namespace syntax is not supported. Take a look here: http://wiki.alfresco.com/wiki/Search#Path_Queries
You'll have to use the prefix version. But, please don't use a regex to get the prefix. There is an org.alfresco.service.namespace.NamespacePrefixResolver (bean NamespaceService) taht defines a method Collection<String> getPrefixes(String namespaceURI).
your dummy code to get the QNamePath of a node:
Path path = nodeService.getPath(folder);
final Map<String, String> cache = new HashMap<String, String>();
final StringBuilder buf = new StringBuilder(128);
for (final Path.Element e : path)
{
if (e instanceof Path.ChildAssocElement)
{
final QName qname = ((Path.ChildAssocElement)e).getRef().getQName();
if (qname != null)
{
String prefix = cache.get(qname.getNamespaceURI());
if (prefix == null)
{
// first request for this namespace prefix, get and cache result
Collection<String> prefixes = ns.getPrefixes(qname.getNamespaceURI());
prefix = prefixes.size() != 0 ? prefixes.iterator().next() : "";
cache.put(qname.getNamespaceURI(), prefix);
}
buf.append('/').append(prefix).append(':').append(ISO9075.encode(qname.getLocalName()));
}
}
else
{
buf.append('/').append(e.toString());
}
}
String searchPath = buf.toString();

Related

How will neo4j jdbc (bolt) handle queries that return a list of nodes?

In neo4j jdbc (bolt), Node is returned as Map , but if you make a query that returns a list of Nodes, getObject () will return a list of InternalNodes. Entities in this list can not be identified by type instanceof, so reflection will identify the node by type name and you will get the value by calling the method by reflection.You can get the value by doing the following, but is this approach correct? rs is ResultSet.entity is return value of this method.
Object columnObject = rs.getObject(columnName);
if (columnObject instanceof List<?>){
List<Map<String,Object>> objectValue = arrayList();
Array columnArray = rs.getArray(columnName);
Object[] columnArrayValues = (Object[]) columnArray.getArray();
for (int iTmp = 0; iTmp < columnArrayValues.length; iTmp++){
Map<String, Object> colArrayItemMap = new HashMap<>();
Object colItemObj = columnArrayValues[iTmp];
Class colItemClass = colItemObj.getClass();
if (colItemClass.getName().equals("org.neo4j.driver.internal.InternalNode")){
Method asMap = colItemClass.getMethod("asMap");
Method getId = colItemClass.getMethod("id");
Method getLabels = colItemClass.getMethod("labels");
colArrayItemMap.put("_id", getId.invoke(colItemObj));
colArrayItemMap.put("_labels", getLabels.invoke(colItemObj));
colArrayItemMap.putAll((Map<? extends String, ?>) asMap.invoke(colItemObj));
} else {
colArrayItemMap.put("_raw", columnArrayValues[iTmp]);
}
objectValue.add(colArrayItemMap);
}
((Map) entity).put(propertyName, objectValue);
} else {
((Map) entity).put(propertyName, columnObject);
}
Such queries are generated by such cypher statements.Such queries are generated by such cypher statements.
MATCH
(input:Input),
(output:Output)
WITH input, output
MATCH
(input)-[:INPUT*1]->(in),
(out)-[:OUTPUT*1]->(output),
g = (in)-[connect:CONNECT*0..5]->(out)
RETURN
input, output, extract(x IN nodes(g)|x) as nodes
It was for different class loaders that we can not identify with the instanceof operator.Since the jdbc driver was placed in Tomcat / lib, it was judged to be different from the class loaded by the application.
In any case, it will be provided by converting List to List or until getResults() is supported as the return value of getArray() It is thought that it is necessary to write.

How to use ES Java API to create a new type of an index

I have succeed create an index use Client , the code like this :
public static boolean addIndex(Client client,String index) throws Exception {
if(client == null){
client = getSettingClient();
}
CreateIndexRequestBuilder requestBuilder = client.admin().indices().prepareCreate(index);
CreateIndexResponse response = requestBuilder.execute().actionGet();
return response.isAcknowledged();
//client.close();
}
public static boolean addIndexType(Client client, String index, String type) throws Exception {
if (client == null) {
client = getSettingClient();
}
TypesExistsAction action = TypesExistsAction.INSTANCE;
TypesExistsRequestBuilder requestBuilder = new TypesExistsRequestBuilder(client, action, index);
requestBuilder.setTypes(type);
TypesExistsResponse response = requestBuilder.get();
return response.isExists();
}
however, the method of addIndexType is not effected, the type is not create .
I don't know how to create type ?
You can create types when you create the index by providing a proper mapping configuration. Alternatively a type gets created when you index a document of a certain type. However the first suggestion is the better one, because then you can control the full mapping of that type instead of relying on dynamic mapping.
You can set types in the following way:
// JSON schema is the JSON mapping which you want to give for the index.
JSONObject builder = new JSONObject().put(type, JSONSchema);
// And then just fire the below command
client.admin().indices().preparePutMapping(indexName)
.setType(type)
.setSource(builder.toString(), XContentType.JSON)
.execute()
.actionGet();

eclipse scout image change

I am trying to change image inside Image view.
I know that getTestImageField().setImageId(Icons.Logo); would not work, because it would not refresh renderer.
Because I need to use setImage(), I need a way to get Image from Icons class.
As Patrick suggested I try
final IconProviderService provider = SERVICES.getService(IconProviderService.class);
final IconSpec ic = provider.getIconSpec(AbstractIcons.StatusError);
final byte[] content = ic.getContent();
but my problem is that ic is always null.
While I debug this I notice that inside IconProviderService.class in line 57 :
#Override
protected URL findResource(String fullPath) {
URL[] entries = FileLocator.findEntries(m_hostBundle, new Path(fullPath));
if (entries != null && entries.length > 0) {
URL url = entries[entries.length - 1];
if (LOG.isDebugEnabled()) {
LOG.debug("find image " + fullPath + " in bundle " + m_hostBundle.getSymbolicName() + "->" + url);
}
return url;
}
return null;
}
URL[] entries is always empty no matter witch icon I try to present.
After further debugging I found out that FileLocator tries to find fragments from bundle, and then look for the path inside this fragments. (line 242)
Bundle[] fragments = activator.getFragments(b);
but Bundle[] fragments is always null.
Normally my bundle b is (Bundle) EquinoxBundle : org.eclipse.scout.rt.ui.rap.mobile_4.0.100.20140829-1424.
I want to try with different bundle so I do :
final BundleContext context = Activator.getDefault().getBundle().getBundleContext();
for (final Bundle b : context.getBundles()) {
final IconProviderService provider = SERVICES.getService(IconProviderService.class);
provider.setHostBundle(b);
final IconSpec ic = provider.getIconSpec(AbstractIcons.StatusError);
if (ic != null) {
final byte[] content = ic.getContent();
imageField().setImage(content);
}
}
but fragments (from above code) is always null.
You can obtain the image content (byte[]) that you can set on the image field as follows:
IconProviderService provider = SERVICES.getService(IconProviderService.class);
byte[] content = provider.getIconSpec(Icons.YourIconName).getContent();
getImageField().setImage(content);
I quickly checked it and it works for me.
Please ensure that the icon is available and you set up the icon provider service as explained in this Wiki Article

Unable to deserialize ArrayOfString back to List<string> in C#

I have seen this question asked, but have not found answers that work so I am asking it again.
I have a restful web service with a POST method that returns a serialized List.
<ArrayOfstring xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<string>QoL5vA8OKgydWIn%2fdWiu70nobBrJo4N9iXeHmtM7Aj4%3d</string>
<string>vxHyJiSSSvDSZWXOdcfl5FMQC97xxGEWDO8Zy8Qp3X5CwADUbEE8ifACQHR1n7uamEaIUbf85ZuBDB8FFCNY2tJAMJ2jNw09SqGVTpMU5uI06DLtuYnJqsPIF735NOhlvRhBLPnpp62DFMCVsDNHy55UBF3Ggi06ZWTiJ8LTYIf3FYiFLPpXLZ1wWeE5chAWQGfz7zDYJa1OgSZ</string>
<string>OqGAT7Yqe6DfyVD29BeIXFyGtabVCloaC9FA1Fp20JkJ9T17ZzyqhnGxwWda7FqqyJUM8YK9OdcOCgTYrl4JxalECdtJm75TdSG8IAPQlFHp6Gidg4EwZaO9FKahlYMm5JrFpxTmLrdLgMAkYEV7gIR6zIyIByAGwYYDDwH3QCHrym3CuueRnFWAHCJu1LJbx0zRtt7g3yEaTiJ</string>
</ArrayOfstring>
The code performing the call is as follows below.
XDocument xDocResponse = RestPOSTToXDocument(szBaseUri, szInput);
string szNamespace = xDocResponse.Root.Name.Namespace.ToString();
IXmlUtils utility = new XmlUtils();
List<string> lst = utility.DeserializeList<string>(xDocResponse, szNamespace);
I have also attempted a different version of the call as shown below.
List<List<string>> lst = utility.DeserializeList<List<string>>(xDocResponse, szNamespace);
Both versions of the calls generate the error provided below.
An exception of type 'System.InvalidOperationException' occurred in System.Xml.dll but was not handled in user code
Additional information: There is an error in XML document (0, 0).
My Deserialize method is provided below.
public List<T> DeserializeList<T>(XDocument doc, string szNamespace)
{
List<T> result = null;
XmlSerializer serializer = new XmlSerializer(typeof(List<T>), szNamespace);
using (System.Xml.XmlReader reader = doc.CreateReader())
{
result = (List<T>)serializer.Deserialize(reader);
}
return result;
}
The XML within the XDocument is valid, so I do not understand why this error is being generated. Also, even if I attempt to get the elements via navigation in the XDocument, it does not work. If I look at the doc.Root.value, it appears that all of the strings are concatenated together into a single string.
Does anyone have any information on how I may deserialize this XDocument into a List?
Thanks to the assistance of mellamokb, I found the problem. When my List is serialized, it is serialized into an ArrayOfstring. If I take the XML and replace ArrayOfstring with ArrayOfString, the deserialization works.
This does not make much sense. I would welcome an explanation of why this is necessary though it may have something to do with String vs string.
Essentially, I had to do the following:
string szXml = xDocResponse.ToString();
int nEndRoot = szXml.IndexOf(">");
szXml = szXml.Replace("ArrayOfstring", "ArrayOfString");
xDocResponse = utility.LoadXDocument(szXml);
string szNamespace = xDocResponse.Root.Name.Namespace.ToString();
List<string> lst = utility.DeserializeList<string>(xDocResponse, szNamespace);
Simply get the response stream and deserealize into string array and store it to List
Code Snippet:
List<string> listNew=new List<string>();
using (Stream answer = webResponse.GetResponseStream())
{
DataContractSerializer xmlSer = new DataContractSerializer(typeof(string[]));
var stringArr= (string[])xmlSer.ReadObject(answer);
foreach (string item in GenreList)
{
listNew.Add(item);
}
}

How to set the default namespace or how to define the #key values when using google-api and using Atom serialization/parser

I'm having trouble with Atom parsing/serializing - clearly something related to the namespace and the default alias - but I can;t figure out what I'm doing wrong.
I have two methods - one that I'm trying to do a GET and see if an album is defined and what that tries to do a POST to create the album (if it does not exist).
The GET I managed to get working - although there too I'm pretty sure I am doing something wrong because it is different from the PicasaAndroidSample. Specifically, if I define:
public class EDAlbum {
#Key("atom:title")
public String title;
#Key("atom:summary")
public String summary;
#Key("atom:gphoto:access")
public String access;
#Key("atom:category")
public EDCategory category = EDCategory.newKind("album");
}
Then the following code does indeed get all the albums:
PicasaUrl url = PicasaUrl.relativeToRoot("feed/api/user/default");
HttpRequest request = EDApplication.getRequest(url);
HttpResponse res = request.execute();
EDAlbumFeed feed = res.parseAs(EDAlbumFeed.class);
boolean hasEDAlbum = false;
for (EDAlbum album : feed.items) {
if (album.title.equals(EDApplication.ED_ALBUM_NAME)) {
hasEDAlbum = true;
break;
}
}
But - if instead I have:
public class EDAlbum {
#Key("title")
public String title;
#Key("summary")
public String summary;
#Key("gphoto:access")
public String access;
#Key("category")
public EDCategory category = EDCategory.newKind("album");
}
Then the feed has an empty collection - i.e. the parser does not know that this is Atom (my guess).
I can live with the android:title in my classes - I don;t get it, but it works.
The problem is that I can't get the POST to wok (to create the album). This code is:
EDAlbum a = new EDAlbum();
a.access = "public";
a.title = EDApplication.ED_ALBUM_NAME;
a.summary = c.getString(R.string.ed_album_summary);
AtomContent content = new AtomContent();
content.entry = a;
content.namespaceDictionary = EDApplication.getNamespaceDictionary();
PicasaUrl url = PicasaUrl.relativeToRoot("feed/api/user/default");
HttpRequest request = EDApplication.postRequest(url, content);
HttpResponse res = request.execute();
The transport and namespace are:
private static final HttpTransport transport = new ApacheHttpTransport(); // my libraries don;t include GoogleTransport.
private static HttpRequestFactory createRequestFactory(final HttpTransport transport) {
return transport.createRequestFactory(new HttpRequestInitializer() {
public void initialize(HttpRequest request) {
AtomParser parser = new AtomParser();
parser.namespaceDictionary = getNamespaceDictionary();
request.addParser(parser);
}
});
}
public static XmlNamespaceDictionary getNamespaceDictionary() {
if (nsDictionary == null) {
nsDictionary = new XmlNamespaceDictionary();
nsDictionary.set("", "http://www.w3.org/2005/Atom");
nsDictionary.set("atom", "http://www.w3.org/2005/Atom");
nsDictionary.set("exif", "http://schemas.google.com/photos/exif/2007");
nsDictionary.set("gd", "http://schemas.google.com/g/2005");
nsDictionary.set("geo", "http://www.w3.org/2003/01/geo/wgs84_pos#");
nsDictionary.set("georss", "http://www.georss.org/georss");
nsDictionary.set("gml", "http://www.opengis.net/gml");
nsDictionary.set("gphoto", "http://schemas.google.com/photos/2007");
nsDictionary.set("media", "http://search.yahoo.com/mrss/");
nsDictionary.set("openSearch", "http://a9.com/-/spec/opensearch/1.1/");
nsDictionary.set("xml", "http://www.w3.org/XML/1998/namespace");
}
return nsDictionary;
}
If I use
#Key("title")
public String title;
then I get an exception that it does not have a default namespace:
W/System.err( 1957): java.lang.IllegalArgumentException: unrecognized alias: (default)
W/System.err( 1957): at com.google.common.base.Preconditions.checkArgument(Preconditions.java:115)
W/System.err( 1957): at com.google.api.client.xml.XmlNamespaceDictionary.getNamespaceUriForAliasHandlingUnknown(XmlNamespaceDictionary.java:288)
W/System.err( 1957): at com.google.api.client.xml.XmlNamespaceDictionary.startDoc(XmlNamespaceDictionary.java:224)
and if I use
#Key("atom:title")
public String title;
then it does serialize but each element has the atom: prefix and the call fails - when I to a tcpdump on it I see something like
.`....<? xml vers
ion='1.0 ' encodi
ng='UTF- 8' ?><at
om:entry xmlns:a
tom="htt p://www.
w3.org/2 005/Atom
"><atom: category
scheme= "http://
schemas. google.c
om/g/200 5#kind"
term="ht tp://sch
emas.goo gle.com/
photos/2 007#albu
m" /><at om:gphot
o:access >public<
/atom:gp hoto:acc
....
What do I need to do different in order to use
#Key("title")
public String title;
and have both the GET and the POST manage the namespace?
It looks you are adding either duplicate dictonary keys or keys that are not understood by the serializer.
Use the following instead.
static final XmlNamespaceDictionary DICTIONARY = new XmlNamespaceDictionary()
.set("", "http://www.w3.org/2005/Atom")
.set("activity", "http://activitystrea.ms/spec/1.0/")
.set("georss", "http://www.georss.org/georss")
.set("media", "http://search.yahoo.com/mrss/")
.set("thr", "http://purl.org/syndication/thread/1.0");
Removing the explicit set for the "atom" item namespace solved this issue for me.

Resources