You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by bo...@apache.org on 2015/03/18 00:33:33 UTC
[11/17] incubator-ranger git commit: Support for Solr as Audit
Destination.
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/FieldAnalysisRequest.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/FieldAnalysisRequest.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/FieldAnalysisRequest.java
new file mode 100644
index 0000000..66ef535
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/FieldAnalysisRequest.java
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj.request;
+
+import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.response.FieldAnalysisResponse;
+import org.apache.solr.common.params.AnalysisParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.ContentStream;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A request for the org.apache.solr.handler.FieldAnalysisRequestHandler.
+ *
+ *
+ * @since solr.14
+ */
+public class FieldAnalysisRequest extends SolrRequest<FieldAnalysisResponse> {
+
+ private String fieldValue;
+ private String query;
+ private boolean showMatch;
+ private List<String> fieldNames;
+ private List<String> fieldTypes;
+
+ /**
+ * Constructs a new FieldAnalysisRequest with a default uri of "/fieldanalysis".
+ */
+ public FieldAnalysisRequest() {
+ super(METHOD.GET, "/analysis/field");
+ }
+
+ /**
+ * Constructs a new FieldAnalysisRequest with a given uri.
+ *
+ * @param uri the uri of the request handler.
+ */
+ public FieldAnalysisRequest(String uri) {
+ super(METHOD.GET, uri);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Collection<ContentStream> getContentStreams() throws IOException {
+ return null;
+ }
+
+ @Override
+ protected FieldAnalysisResponse createResponse(SolrClient client) {
+ if (fieldTypes == null && fieldNames == null) {
+ throw new IllegalStateException("At least one field type or field name need to be specified");
+ }
+ if (fieldValue == null) {
+ throw new IllegalStateException("The field value must be set");
+ }
+ return new FieldAnalysisResponse();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SolrParams getParams() {
+ ModifiableSolrParams params = new ModifiableSolrParams();
+ params.set(AnalysisParams.FIELD_VALUE, fieldValue);
+ if (query != null) {
+ params.add(AnalysisParams.QUERY, query);
+ params.add(AnalysisParams.SHOW_MATCH, String.valueOf(showMatch));
+ }
+ if (fieldNames != null) {
+ String fieldNameValue = listToCommaDelimitedString(fieldNames);
+ params.add(AnalysisParams.FIELD_NAME, fieldNameValue);
+ }
+ if (fieldTypes != null) {
+ String fieldTypeValue = listToCommaDelimitedString(fieldTypes);
+ params.add(AnalysisParams.FIELD_TYPE, fieldTypeValue);
+ }
+ return params;
+ }
+
+ //================================================ Helper Methods ==================================================
+
+ /**
+ * Convers the given list of string to a comma-separated string.
+ *
+ * @param list The list of string.
+ *
+ * @return The comma-separated string.
+ */
+ static String listToCommaDelimitedString(List<String> list) {
+ StringBuilder result = new StringBuilder();
+ for (String str : list) {
+ if (result.length() > 0) {
+ result.append(",");
+ }
+ result.append(str);
+ }
+ return result.toString();
+ }
+
+
+ //============================================ Setter/Getter Methods ===============================================
+
+ /**
+ * Sets the field value to be analyzed.
+ *
+ * @param fieldValue The field value to be analyzed.
+ *
+ * @return This FieldAnalysisRequest (fluent interface support).
+ */
+ public FieldAnalysisRequest setFieldValue(String fieldValue) {
+ this.fieldValue = fieldValue;
+ return this;
+ }
+
+ /**
+ * Returns the field value that will be analyzed when this request is processed.
+ *
+ * @return The field value that will be analyzed when this request is processed.
+ */
+ public String getFieldValue() {
+ return fieldValue;
+ }
+
+ /**
+ * Sets the query to be analyzed. May be {@code null} indicated that no query analysis should take place.
+ *
+ * @param query The query to be analyzed.
+ *
+ * @return This FieldAnalysisRequest (fluent interface support).
+ */
+ public FieldAnalysisRequest setQuery(String query) {
+ this.query = query;
+ return this;
+ }
+
+ /**
+ * Returns the query that will be analyzed. May return {@code null} indicating that no query analysis will be
+ * performed.
+ *
+ * @return The query that will be analyzed. May return {@code null} indicating that no query analysis will be
+ * performed.
+ */
+ public String getQuery() {
+ return query;
+ }
+
+ /**
+ * Sets whether index time tokens that match query time tokens should be marked as a "match". By default this is set
+ * to {@code false}. Obviously, this flag is ignored if when the query is set to {@code null}.
+ *
+ * @param showMatch Sets whether index time tokens that match query time tokens should be marked as a "match".
+ *
+ * @return This FieldAnalysisRequest (fluent interface support).
+ */
+ public FieldAnalysisRequest setShowMatch(boolean showMatch) {
+ this.showMatch = showMatch;
+ return this;
+ }
+
+ /**
+ * Returns whether index time tokens that match query time tokens should be marked as a "match".
+ *
+ * @return Whether index time tokens that match query time tokens should be marked as a "match".
+ *
+ * @see #setShowMatch(boolean)
+ */
+ public boolean isShowMatch() {
+ return showMatch;
+ }
+
+ /**
+ * Adds the given field name for analysis.
+ *
+ * @param fieldName A field name on which the analysis should be performed.
+ *
+ * @return this FieldAnalysisRequest (fluent interface support).
+ */
+ public FieldAnalysisRequest addFieldName(String fieldName) {
+ if (fieldNames == null) {
+ fieldNames = new LinkedList<>();
+ }
+ fieldNames.add(fieldName);
+ return this;
+ }
+
+ /**
+ * Sets the field names on which the analysis should be performed.
+ *
+ * @param fieldNames The field names on which the analysis should be performed.
+ *
+ * @return this FieldAnalysisRequest (fluent interface support).
+ */
+ public FieldAnalysisRequest setFieldNames(List<String> fieldNames) {
+ this.fieldNames = fieldNames;
+ return this;
+ }
+
+ /**
+ * Returns a list of field names the analysis should be performed on. May return {@code null} indicating that no
+ * analysis will be performed on field names.
+ *
+ * @return The field names the analysis should be performed on.
+ */
+ public List<String> getFieldNames() {
+ return fieldNames;
+ }
+
+ /**
+ * Adds the given field type for analysis.
+ *
+ * @param fieldTypeName A field type name on which analysis should be performed.
+ *
+ * @return This FieldAnalysisRequest (fluent interface support).
+ */
+ public FieldAnalysisRequest addFieldType(String fieldTypeName) {
+ if (fieldTypes == null) {
+ fieldTypes = new LinkedList<>();
+ }
+ fieldTypes.add(fieldTypeName);
+ return this;
+ }
+
+/**
+ * Sets the field types on which analysis should be performed.
+ *
+ * @param fieldTypes The field type names on which analysis should be performed.
+ *
+ * @return This FieldAnalysisRequest (fluent interface support).
+ */
+ public FieldAnalysisRequest setFieldTypes(List<String> fieldTypes) {
+ this.fieldTypes = fieldTypes;
+ return this;
+ }
+
+
+ /**
+ * Returns a list of field types the analysis should be performed on. May return {@code null} indicating that no
+ * analysis will be peformed on field types.
+ *
+ * @return The field types the analysis should be performed on.
+ */
+ public List<String> getFieldTypes() {
+ return fieldTypes;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/IsUpdateRequest.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/IsUpdateRequest.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/IsUpdateRequest.java
new file mode 100644
index 0000000..ec49e30
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/IsUpdateRequest.java
@@ -0,0 +1,26 @@
+package org.apache.solr.client.solrj.request;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * Marker class so that we can determine which requests are updates.
+ */
+public interface IsUpdateRequest {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
new file mode 100644
index 0000000..7bb64b4
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/JavaBinUpdateRequestCodec.java
@@ -0,0 +1,251 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.client.solrj.request;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.DataInputInputStream;
+import org.apache.solr.common.util.JavaBinCodec;
+import org.apache.solr.common.util.NamedList;
+
+/**
+ * Provides methods for marshalling an UpdateRequest to a NamedList which can be serialized in the javabin format and
+ * vice versa.
+ *
+ *
+ * @see org.apache.solr.common.util.JavaBinCodec
+ * @since solr 1.4
+ */
+public class JavaBinUpdateRequestCodec {
+
+ /**
+ * Converts an UpdateRequest to a NamedList which can be serialized to the given OutputStream in the javabin format
+ *
+ * @param updateRequest the UpdateRequest to be written out
+ * @param os the OutputStream to which the request is to be written
+ *
+ * @throws IOException in case of an exception during marshalling or writing to the stream
+ */
+ public void marshal(UpdateRequest updateRequest, OutputStream os) throws IOException {
+ NamedList nl = new NamedList();
+ NamedList params = solrParamsToNamedList(updateRequest.getParams());
+ if (updateRequest.getCommitWithin() != -1) {
+ params.add("commitWithin", updateRequest.getCommitWithin());
+ }
+ Iterator<SolrInputDocument> docIter = null;
+
+ if(updateRequest.getDocIterator() != null){
+ docIter = updateRequest.getDocIterator();
+ }
+
+ Map<SolrInputDocument,Map<String,Object>> docMap = updateRequest.getDocumentsMap();
+
+ nl.add("params", params);// 0: params
+ if (updateRequest.getDeleteByIdMap() != null) {
+ nl.add("delByIdMap", updateRequest.getDeleteByIdMap());
+ }
+ nl.add("delByQ", updateRequest.getDeleteQuery());
+
+ if (docMap != null) {
+ nl.add("docsMap", docMap.entrySet().iterator());
+ } else {
+ if (updateRequest.getDocuments() != null) {
+ docIter = updateRequest.getDocuments().iterator();
+ }
+ nl.add("docs", docIter);
+ }
+ JavaBinCodec codec = new JavaBinCodec();
+ codec.marshal(nl, os);
+ }
+
+ /**
+ * Reads a NamedList from the given InputStream, converts it into a SolrInputDocument and passes it to the given
+ * StreamingUpdateHandler
+ *
+ * @param is the InputStream from which to read
+ * @param handler an instance of StreamingUpdateHandler to which SolrInputDocuments are streamed one by one
+ *
+ * @return the UpdateRequest
+ *
+ * @throws IOException in case of an exception while reading from the input stream or unmarshalling
+ */
+ public UpdateRequest unmarshal(InputStream is, final StreamingUpdateHandler handler) throws IOException {
+ final UpdateRequest updateRequest = new UpdateRequest();
+ List<List<NamedList>> doclist;
+ List<Entry<SolrInputDocument,Map<Object,Object>>> docMap;
+ List<String> delById;
+ Map<String,Map<String,Object>> delByIdMap;
+ List<String> delByQ;
+ final NamedList[] namedList = new NamedList[1];
+ JavaBinCodec codec = new JavaBinCodec() {
+
+ // NOTE: this only works because this is an anonymous inner class
+ // which will only ever be used on a single stream -- if this class
+ // is ever refactored, this will not work.
+ private boolean seenOuterMostDocIterator = false;
+
+ @Override
+ public NamedList readNamedList(DataInputInputStream dis) throws IOException {
+ int sz = readSize(dis);
+ NamedList nl = new NamedList();
+ if (namedList[0] == null) {
+ namedList[0] = nl;
+ }
+ for (int i = 0; i < sz; i++) {
+ String name = (String) readVal(dis);
+ Object val = readVal(dis);
+ nl.add(name, val);
+ }
+ return nl;
+ }
+
+ @Override
+ public List readIterator(DataInputInputStream fis) throws IOException {
+
+ // default behavior for reading any regular Iterator in the stream
+ if (seenOuterMostDocIterator) return super.readIterator(fis);
+
+ // special treatment for first outermost Iterator
+ // (the list of documents)
+ seenOuterMostDocIterator = true;
+ return readOuterMostDocIterator(fis);
+ }
+
+ private List readOuterMostDocIterator(DataInputInputStream fis) throws IOException {
+ NamedList params = (NamedList) namedList[0].get("params");
+ updateRequest.setParams(new ModifiableSolrParams(SolrParams.toSolrParams(params)));
+ if (handler == null) return super.readIterator(fis);
+ Integer commitWithin = null;
+ Boolean overwrite = null;
+ while (true) {
+ Object o = readVal(fis);
+ if (o == END_OBJ) break;
+ SolrInputDocument sdoc = null;
+ if (o instanceof List) {
+ sdoc = listToSolrInputDocument((List<NamedList>) o);
+ } else if (o instanceof NamedList) {
+ UpdateRequest req = new UpdateRequest();
+ req.setParams(new ModifiableSolrParams(SolrParams.toSolrParams((NamedList) o)));
+ handler.update(null, req, null, null);
+ } else if (o instanceof Map.Entry){
+ sdoc = (SolrInputDocument) ((Map.Entry) o).getKey();
+ Map p = (Map) ((Map.Entry) o).getValue();
+ if (p != null) {
+ commitWithin = (Integer) p.get(UpdateRequest.COMMIT_WITHIN);
+ overwrite = (Boolean) p.get(UpdateRequest.OVERWRITE);
+ }
+ } else {
+
+ sdoc = (SolrInputDocument) o;
+ }
+ handler.update(sdoc, updateRequest, commitWithin, overwrite);
+ }
+ return Collections.EMPTY_LIST;
+ }
+
+ };
+
+ codec.unmarshal(is);
+
+ // NOTE: if the update request contains only delete commands the params
+ // must be loaded now
+ if(updateRequest.getParams()==null) {
+ NamedList params = (NamedList) namedList[0].get("params");
+ if(params!=null) {
+ updateRequest.setParams(new ModifiableSolrParams(SolrParams.toSolrParams(params)));
+ }
+ }
+ delById = (List<String>) namedList[0].get("delById");
+ delByIdMap = (Map<String,Map<String,Object>>) namedList[0].get("delByIdMap");
+ delByQ = (List<String>) namedList[0].get("delByQ");
+ doclist = (List) namedList[0].get("docs");
+ Object docsMapObj = namedList[0].get("docsMap");
+
+ if (docsMapObj instanceof Map) {//SOLR-5762
+ docMap = new ArrayList(((Map)docsMapObj).entrySet());
+ } else {
+ docMap = (List<Entry<SolrInputDocument, Map<Object, Object>>>) docsMapObj;
+ }
+
+
+ // we don't add any docs, because they were already processed
+ // deletes are handled later, and must be passed back on the UpdateRequest
+
+ if (delById != null) {
+ for (String s : delById) {
+ updateRequest.deleteById(s);
+ }
+ }
+ if (delByIdMap != null) {
+ for (Map.Entry<String,Map<String,Object>> entry : delByIdMap.entrySet()) {
+ Map<String,Object> params = entry.getValue();
+ if (params != null) {
+ Long version = (Long) params.get(UpdateRequest.VER);
+ if (params.containsKey(UpdateRequest.ROUTE))
+ updateRequest.deleteById(entry.getKey(), (String) params.get(UpdateRequest.ROUTE));
+ else
+ updateRequest.deleteById(entry.getKey(), version);
+ } else {
+ updateRequest.deleteById(entry.getKey());
+ }
+
+ }
+ }
+ if (delByQ != null) {
+ for (String s : delByQ) {
+ updateRequest.deleteByQuery(s);
+ }
+ }
+
+ return updateRequest;
+ }
+
+ private SolrInputDocument listToSolrInputDocument(List<NamedList> namedList) {
+ SolrInputDocument doc = new SolrInputDocument();
+ for (int i = 0; i < namedList.size(); i++) {
+ NamedList nl = namedList.get(i);
+ if (i == 0) {
+ doc.setDocumentBoost(nl.getVal(0) == null ? 1.0f : (Float) nl.getVal(0));
+ } else {
+ doc.addField((String) nl.getVal(0),
+ nl.getVal(1),
+ nl.getVal(2) == null ? 1.0f : (Float) nl.getVal(2));
+ }
+ }
+ return doc;
+ }
+
+ private NamedList solrParamsToNamedList(SolrParams params) {
+ if (params == null) return new NamedList();
+ return params.toNamedList();
+ }
+
+ public static interface StreamingUpdateHandler {
+ public void update(SolrInputDocument document, UpdateRequest req, Integer commitWithin, Boolean override);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/LukeRequest.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/LukeRequest.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/LukeRequest.java
new file mode 100644
index 0000000..82b5330
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/LukeRequest.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj.request;
+
+import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.response.LukeResponse;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.ContentStream;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ *
+ *
+ * @since solr 1.3
+ */
+public class LukeRequest extends SolrRequest<LukeResponse> {
+
+ private List<String> fields;
+ private int numTerms = -1;
+ private boolean showSchema = false;
+
+ public LukeRequest()
+ {
+ super( METHOD.GET, "/admin/luke" );
+ }
+
+ public LukeRequest( String path )
+ {
+ super( METHOD.GET, path );
+ }
+
+ //---------------------------------------------------------------------------------
+ //---------------------------------------------------------------------------------
+
+ public void addField( String f )
+ {
+ if( fields == null ) {
+ fields = new ArrayList<>();
+ }
+ fields.add( f );
+ }
+
+ public void setFields( List<String> f )
+ {
+ fields = f;
+ }
+
+ //---------------------------------------------------------------------------------
+ //---------------------------------------------------------------------------------
+
+ public boolean isShowSchema() {
+ return showSchema;
+ }
+
+ public void setShowSchema(boolean showSchema) {
+ this.showSchema = showSchema;
+ }
+
+ public int getNumTerms() {
+ return numTerms;
+ }
+
+ /**
+ * the number of terms to return for a given field. If the number is 0, it will not traverse the terms.
+ */
+ public void setNumTerms(int count) {
+ this.numTerms = count;
+ }
+
+ //---------------------------------------------------------------------------------
+ //---------------------------------------------------------------------------------
+
+ @Override
+ public Collection<ContentStream> getContentStreams() {
+ return null;
+ }
+
+ @Override
+ protected LukeResponse createResponse(SolrClient client) {
+ return new LukeResponse();
+ }
+
+ @Override
+ public SolrParams getParams() {
+ ModifiableSolrParams params = new ModifiableSolrParams();
+ if( fields != null && fields.size() > 0 ) {
+ params.add( CommonParams.FL, fields.toArray( new String[fields.size()] ) );
+ }
+ if( numTerms >= 0 ) {
+ params.add( "numTerms", numTerms+"" );
+ }
+ if (showSchema) {
+ params.add("show", "schema");
+ }
+ return params;
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/QueryRequest.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/QueryRequest.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/QueryRequest.java
new file mode 100644
index 0000000..9d47f99
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/QueryRequest.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj.request;
+
+import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.ContentStream;
+
+import java.util.Collection;
+
+/**
+ *
+ *
+ * @since solr 1.3
+ */
+public class QueryRequest extends SolrRequest<QueryResponse> {
+
+ private SolrParams query;
+
+ public QueryRequest()
+ {
+ super( METHOD.GET, null );
+ }
+
+ public QueryRequest( SolrParams q )
+ {
+ super( METHOD.GET, null );
+ query = q;
+ }
+
+ public QueryRequest( SolrParams q, METHOD method )
+ {
+ super( method, null );
+ query = q;
+ }
+
+ /**
+ * Use the params 'QT' parameter if it exists
+ */
+ @Override
+ public String getPath() {
+ String qt = query == null ? null : query.get( CommonParams.QT );
+ if( qt == null ) {
+ qt = super.getPath();
+ }
+ if( qt != null && qt.startsWith( "/" ) ) {
+ return qt;
+ }
+ return "/select";
+ }
+
+ //---------------------------------------------------------------------------------
+ //---------------------------------------------------------------------------------
+
+ @Override
+ public Collection<ContentStream> getContentStreams() {
+ return null;
+ }
+
+ @Override
+ protected QueryResponse createResponse(SolrClient client) {
+ return new QueryResponse(client);
+ }
+
+ @Override
+ public SolrParams getParams() {
+ return query;
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/RequestWriter.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/RequestWriter.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/RequestWriter.java
new file mode 100644
index 0000000..15872b2
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/RequestWriter.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj.request;
+
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.util.ClientUtils;
+import org.apache.solr.common.util.ContentStream;
+import org.apache.solr.common.util.ContentStreamBase;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * A RequestWriter is used to write requests to Solr.
+ * <p>
+ * A subclass can override the methods in this class to supply a custom format in which a request can be sent.
+ *
+ *
+ * @since solr 1.4
+ */
+public class RequestWriter {
+ public static final Charset UTF_8 = StandardCharsets.UTF_8;
+
+ public Collection<ContentStream> getContentStreams(SolrRequest req) throws IOException {
+ if (req instanceof UpdateRequest) {
+ UpdateRequest updateRequest = (UpdateRequest) req;
+ if (isEmpty(updateRequest)) return null;
+ List<ContentStream> l = new ArrayList<>();
+ l.add(new LazyContentStream(updateRequest));
+ return l;
+ }
+ return req.getContentStreams();
+ }
+
+ private boolean isEmpty(UpdateRequest updateRequest) {
+ return isNull(updateRequest.getDocuments()) &&
+ isNull(updateRequest.getDeleteByIdMap()) &&
+ isNull(updateRequest.getDeleteQuery()) &&
+ updateRequest.getDocIterator() == null;
+ }
+
+ public String getPath(SolrRequest req) {
+ return req.getPath();
+ }
+
+ public ContentStream getContentStream(UpdateRequest req) throws IOException {
+ return new ContentStreamBase.StringStream(req.getXML());
+ }
+
+ public void write(SolrRequest request, OutputStream os) throws IOException {
+ if (request instanceof UpdateRequest) {
+ UpdateRequest updateRequest = (UpdateRequest) request;
+ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, UTF_8));
+ updateRequest.writeXML(writer);
+ writer.flush();
+ }
+ }
+
+ public String getUpdateContentType() {
+ return ClientUtils.TEXT_XML;
+
+ }
+
+ public class LazyContentStream implements ContentStream {
+ ContentStream contentStream = null;
+ UpdateRequest req = null;
+
+ public LazyContentStream(UpdateRequest req) {
+ this.req = req;
+ }
+
+ private ContentStream getDelegate() {
+ if (contentStream == null) {
+ try {
+ contentStream = getContentStream(req);
+ } catch (IOException e) {
+ throw new RuntimeException("Unable to write xml into a stream", e);
+ }
+ }
+ return contentStream;
+ }
+
+ @Override
+ public String getName() {
+ return getDelegate().getName();
+ }
+
+ @Override
+ public String getSourceInfo() {
+ return getDelegate().getSourceInfo();
+ }
+
+ @Override
+ public String getContentType() {
+ return getUpdateContentType();
+ }
+
+ @Override
+ public Long getSize() {
+ return getDelegate().getSize();
+ }
+
+ @Override
+ public InputStream getStream() throws IOException {
+ return getDelegate().getStream();
+ }
+
+ @Override
+ public Reader getReader() throws IOException {
+ return getDelegate().getReader();
+ }
+
+ public void writeTo(OutputStream os) throws IOException {
+ write(req, os);
+
+ }
+ }
+
+ protected boolean isNull(List l) {
+ return l == null || l.isEmpty();
+ }
+
+ protected boolean isNull(Map l) {
+ return l == null || l.isEmpty();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/SolrPing.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/SolrPing.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/SolrPing.java
new file mode 100644
index 0000000..00ad41f
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/SolrPing.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj.request;
+
+import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.response.SolrPingResponse;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.ContentStream;
+
+import java.util.Collection;
+
+/**
+ * Verify that there is a working Solr core at the URL of a {@link org.apache.solr.client.solrj.SolrClient}.
+ * To use this class, the solrconfig.xml for the relevant core must include the
+ * request handler for <code>/admin/ping</code>.
+ *
+ * @since solr 1.3
+ */
+public class SolrPing extends SolrRequest<SolrPingResponse> {
+
+ /** serialVersionUID. */
+ private static final long serialVersionUID = 5828246236669090017L;
+
+ /** Request parameters. */
+ private ModifiableSolrParams params;
+
+ /**
+ * Create a new SolrPing object.
+ */
+ public SolrPing() {
+ super(METHOD.GET, CommonParams.PING_HANDLER);
+ params = new ModifiableSolrParams();
+ }
+
+ @Override
+ public Collection<ContentStream> getContentStreams() {
+ return null;
+ }
+
+ @Override
+ protected SolrPingResponse createResponse(SolrClient client) {
+ return new SolrPingResponse();
+ }
+
+ @Override
+ public ModifiableSolrParams getParams() {
+ return params;
+ }
+
+ /**
+ * Remove the action parameter from this request. This will result in the same
+ * behavior as {@code SolrPing#setActionPing()}. For Solr server version 4.0
+ * and later.
+ *
+ * @return this
+ */
+ public SolrPing removeAction() {
+ params.remove(CommonParams.ACTION);
+ return this;
+ }
+
+ /**
+ * Set the action parameter on this request to enable. This will delete the
+ * health-check file for the Solr core. For Solr server version 4.0 and later.
+ *
+ * @return this
+ */
+ public SolrPing setActionDisable() {
+ params.set(CommonParams.ACTION, CommonParams.DISABLE);
+ return this;
+ }
+
+ /**
+ * Set the action parameter on this request to enable. This will create the
+ * health-check file for the Solr core. For Solr server version 4.0 and later.
+ *
+ * @return this
+ */
+ public SolrPing setActionEnable() {
+ params.set(CommonParams.ACTION, CommonParams.ENABLE);
+ return this;
+ }
+
+ /**
+ * Set the action parameter on this request to ping. This is the same as not
+ * including the action at all. For Solr server version 4.0 and later.
+ *
+ * @return this
+ */
+ public SolrPing setActionPing() {
+ params.set(CommonParams.ACTION, CommonParams.PING);
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/UpdateRequest.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/UpdateRequest.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/UpdateRequest.java
new file mode 100644
index 0000000..0e6580c
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/UpdateRequest.java
@@ -0,0 +1,463 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj.request;
+
+import org.apache.solr.client.solrj.impl.LBHttpSolrClient;
+import org.apache.solr.client.solrj.util.ClientUtils;
+import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.common.cloud.DocCollection;
+import org.apache.solr.common.cloud.DocRouter;
+import org.apache.solr.common.cloud.Slice;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.ContentStream;
+import org.apache.solr.common.util.XML;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ *
+ *
+ * @since solr 1.3
+ */
+public class UpdateRequest extends AbstractUpdateRequest {
+
+ public static final String REPFACT = "rf";
+ public static final String MIN_REPFACT = "min_rf";
+ public static final String VER = "ver";
+ public static final String ROUTE = "_route_";
+ public static final String OVERWRITE = "ow";
+ public static final String COMMIT_WITHIN = "cw";
+ private Map<SolrInputDocument,Map<String,Object>> documents = null;
+ private Iterator<SolrInputDocument> docIterator = null;
+ private Map<String,Map<String,Object>> deleteById = null;
+ private List<String> deleteQuery = null;
+
+ public UpdateRequest() {
+ super(METHOD.POST, "/update");
+ }
+
+ public UpdateRequest(String url) {
+ super(METHOD.POST, url);
+ }
+
+ // ---------------------------------------------------------------------------
+ // ---------------------------------------------------------------------------
+
+ /**
+ * clear the pending documents and delete commands
+ */
+ public void clear() {
+ if (documents != null) {
+ documents.clear();
+ }
+ if (deleteById != null) {
+ deleteById.clear();
+ }
+ if (deleteQuery != null) {
+ deleteQuery.clear();
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+ // ---------------------------------------------------------------------------
+
+ public UpdateRequest add(final SolrInputDocument doc) {
+ if (documents == null) {
+ documents = new LinkedHashMap<>();
+ }
+ documents.put(doc, null);
+ return this;
+ }
+
+ public UpdateRequest add(final SolrInputDocument doc, Boolean overwrite) {
+ return add(doc, null, overwrite);
+ }
+
+ public UpdateRequest add(final SolrInputDocument doc, Integer commitWithin) {
+ return add(doc, commitWithin, null);
+ }
+
+ public UpdateRequest add(final SolrInputDocument doc, Integer commitWithin,
+ Boolean overwrite) {
+ if (documents == null) {
+ documents = new LinkedHashMap<>();
+ }
+ Map<String,Object> params = new HashMap<>(2);
+ if (commitWithin != null) params.put(COMMIT_WITHIN, commitWithin);
+ if (overwrite != null) params.put(OVERWRITE, overwrite);
+
+ documents.put(doc, params);
+
+ return this;
+ }
+
+ public UpdateRequest add(final Collection<SolrInputDocument> docs) {
+ if (documents == null) {
+ documents = new LinkedHashMap<>();
+ }
+ for (SolrInputDocument doc : docs) {
+ documents.put(doc, null);
+ }
+ return this;
+ }
+
+ public UpdateRequest deleteById(String id) {
+ if (deleteById == null) {
+ deleteById = new LinkedHashMap<>();
+ }
+ deleteById.put(id, null);
+ return this;
+ }
+
+ public UpdateRequest deleteById(String id, String route) {
+ return deleteById(id, route, null);
+ }
+
+ public UpdateRequest deleteById(String id, String route, Long version) {
+ if (deleteById == null) {
+ deleteById = new LinkedHashMap<>();
+ }
+ Map<String, Object> params = (route == null && version == null) ? null : new HashMap<String, Object>(1);
+ if (version != null)
+ params.put(VER, version);
+ if (route != null)
+ params.put(ROUTE, route);
+ deleteById.put(id, params);
+ return this;
+ }
+
+
+ public UpdateRequest deleteById(List<String> ids) {
+ if (deleteById == null) {
+ deleteById = new LinkedHashMap<>();
+ }
+
+ for (String id : ids) {
+ deleteById.put(id, null);
+ }
+
+ return this;
+ }
+
+ public UpdateRequest deleteById(String id, Long version) {
+ return deleteById(id, null, version);
+ }
+
+ public UpdateRequest deleteByQuery(String q) {
+ if (deleteQuery == null) {
+ deleteQuery = new ArrayList<>();
+ }
+ deleteQuery.add(q);
+ return this;
+ }
+
+ /**
+ * @param router to route updates with
+ * @param col DocCollection for the updates
+ * @param urlMap of the cluster
+ * @param params params to use
+ * @param idField the id field
+ * @return a Map of urls to requests
+ */
+ public Map<String,LBHttpSolrClient.Req> getRoutes(DocRouter router,
+ DocCollection col, Map<String,List<String>> urlMap,
+ ModifiableSolrParams params, String idField) {
+
+ if ((documents == null || documents.size() == 0)
+ && (deleteById == null || deleteById.size() == 0)) {
+ return null;
+ }
+
+ Map<String,LBHttpSolrClient.Req> routes = new HashMap<>();
+ if (documents != null) {
+ Set<Entry<SolrInputDocument,Map<String,Object>>> entries = documents.entrySet();
+ for (Entry<SolrInputDocument,Map<String,Object>> entry : entries) {
+ SolrInputDocument doc = entry.getKey();
+ Object id = doc.getFieldValue(idField);
+ if (id == null) {
+ return null;
+ }
+ Slice slice = router.getTargetSlice(id
+ .toString(), doc, null, null, col);
+ if (slice == null) {
+ return null;
+ }
+ List<String> urls = urlMap.get(slice.getName());
+ String leaderUrl = urls.get(0);
+ LBHttpSolrClient.Req request = (LBHttpSolrClient.Req) routes
+ .get(leaderUrl);
+ if (request == null) {
+ UpdateRequest updateRequest = new UpdateRequest();
+ updateRequest.setMethod(getMethod());
+ updateRequest.setCommitWithin(getCommitWithin());
+ updateRequest.setParams(params);
+ updateRequest.setPath(getPath());
+ request = new LBHttpSolrClient.Req(updateRequest, urls);
+ routes.put(leaderUrl, request);
+ }
+ UpdateRequest urequest = (UpdateRequest) request.getRequest();
+ Map<String,Object> value = entry.getValue();
+ Boolean ow = null;
+ if (value != null) {
+ ow = (Boolean) value.get(OVERWRITE);
+ }
+ if (ow != null) {
+ urequest.add(doc, ow);
+ } else {
+ urequest.add(doc);
+ }
+ }
+ }
+
+ // Route the deleteById's
+
+ if (deleteById != null) {
+
+ Iterator<Map.Entry<String,Map<String,Object>>> entries = deleteById.entrySet()
+ .iterator();
+ while (entries.hasNext()) {
+
+ Map.Entry<String,Map<String,Object>> entry = entries.next();
+
+ String deleteId = entry.getKey();
+ Map<String,Object> map = entry.getValue();
+ Long version = null;
+ if (map != null) {
+ version = (Long) map.get(VER);
+ }
+ Slice slice = router.getTargetSlice(deleteId, null, null, null, col);
+ if (slice == null) {
+ return null;
+ }
+ List<String> urls = urlMap.get(slice.getName());
+ String leaderUrl = urls.get(0);
+ LBHttpSolrClient.Req request = routes.get(leaderUrl);
+ if (request != null) {
+ UpdateRequest urequest = (UpdateRequest) request.getRequest();
+ urequest.deleteById(deleteId, version);
+ } else {
+ UpdateRequest urequest = new UpdateRequest();
+ urequest.setParams(params);
+ urequest.deleteById(deleteId, version);
+ request = new LBHttpSolrClient.Req(urequest, urls);
+ routes.put(leaderUrl, request);
+ }
+ }
+ }
+
+ return routes;
+ }
+
+ public void setDocIterator(Iterator<SolrInputDocument> docIterator) {
+ this.docIterator = docIterator;
+ }
+
+ public void setDeleteQuery(List<String> deleteQuery) {
+ this.deleteQuery = deleteQuery;
+ }
+
+ // --------------------------------------------------------------------------
+ // --------------------------------------------------------------------------
+
+ @Override
+ public Collection<ContentStream> getContentStreams() throws IOException {
+ return ClientUtils.toContentStreams(getXML(), ClientUtils.TEXT_XML);
+ }
+
+ public String getXML() throws IOException {
+ StringWriter writer = new StringWriter();
+ writeXML(writer);
+ writer.flush();
+
+ // If action is COMMIT or OPTIMIZE, it is sent with params
+ String xml = writer.toString();
+ // System.out.println( "SEND:"+xml );
+ return (xml.length() > 0) ? xml : null;
+ }
+
+ private List<Map<SolrInputDocument,Map<String,Object>>> getDocLists(Map<SolrInputDocument,Map<String,Object>> documents) {
+ List<Map<SolrInputDocument,Map<String,Object>>> docLists = new ArrayList<>();
+ Map<SolrInputDocument,Map<String,Object>> docList = null;
+ if (this.documents != null) {
+
+ Boolean lastOverwrite = true;
+ Integer lastCommitWithin = -1;
+
+ Set<Entry<SolrInputDocument,Map<String,Object>>> entries = this.documents
+ .entrySet();
+ for (Entry<SolrInputDocument,Map<String,Object>> entry : entries) {
+ Map<String,Object> map = entry.getValue();
+ Boolean overwrite = null;
+ Integer commitWithin = null;
+ if (map != null) {
+ overwrite = (Boolean) entry.getValue().get(OVERWRITE);
+ commitWithin = (Integer) entry.getValue().get(COMMIT_WITHIN);
+ }
+ if (overwrite != lastOverwrite || commitWithin != lastCommitWithin
+ || docLists.size() == 0) {
+ docList = new LinkedHashMap<>();
+ docLists.add(docList);
+ }
+ docList.put(entry.getKey(), entry.getValue());
+ lastCommitWithin = commitWithin;
+ lastOverwrite = overwrite;
+ }
+ }
+
+ if (docIterator != null) {
+ docList = new LinkedHashMap<>();
+ docLists.add(docList);
+ while (docIterator.hasNext()) {
+ SolrInputDocument doc = docIterator.next();
+ if (doc != null) {
+ docList.put(doc, null);
+ }
+ }
+
+ }
+
+ return docLists;
+ }
+
+ /**
+ * @since solr 1.4
+ */
+ public void writeXML(Writer writer) throws IOException {
+ List<Map<SolrInputDocument,Map<String,Object>>> getDocLists = getDocLists(documents);
+
+ for (Map<SolrInputDocument,Map<String,Object>> docs : getDocLists) {
+
+ if ((docs != null && docs.size() > 0)) {
+ Entry<SolrInputDocument,Map<String,Object>> firstDoc = docs.entrySet()
+ .iterator().next();
+ Map<String,Object> map = firstDoc.getValue();
+ Integer cw = null;
+ Boolean ow = null;
+ if (map != null) {
+ cw = (Integer) firstDoc.getValue().get(COMMIT_WITHIN);
+ ow = (Boolean) firstDoc.getValue().get(OVERWRITE);
+ }
+ if (ow == null) ow = true;
+ int commitWithin = (cw != null && cw != -1) ? cw : this.commitWithin;
+ boolean overwrite = ow;
+ if (commitWithin > -1 || overwrite != true) {
+ writer.write("<add commitWithin=\"" + commitWithin + "\" "
+ + "overwrite=\"" + overwrite + "\">");
+ } else {
+ writer.write("<add>");
+ }
+
+ Set<Entry<SolrInputDocument,Map<String,Object>>> entries = docs
+ .entrySet();
+ for (Entry<SolrInputDocument,Map<String,Object>> entry : entries) {
+ ClientUtils.writeXML(entry.getKey(), writer);
+ }
+
+ writer.write("</add>");
+ }
+ }
+
+ // Add the delete commands
+ boolean deleteI = deleteById != null && deleteById.size() > 0;
+ boolean deleteQ = deleteQuery != null && deleteQuery.size() > 0;
+ if (deleteI || deleteQ) {
+ if (commitWithin > 0) {
+ writer.append("<delete commitWithin=\"" + commitWithin + "\">");
+ } else {
+ writer.append("<delete>");
+ }
+ if (deleteI) {
+ for (Map.Entry<String,Map<String,Object>> entry : deleteById.entrySet()) {
+ writer.append("<id");
+ Map<String,Object> map = entry.getValue();
+ if (map != null) {
+ Long version = (Long) map.get(VER);
+ String route = (String)map.get(ROUTE);
+ if (version != null) {
+ writer.append(" version=\"" + version + "\"");
+ }
+
+ if (route != null) {
+ writer.append(" _route_=\"" + route + "\"");
+ }
+ }
+ writer.append(">");
+
+ XML.escapeCharData(entry.getKey(), writer);
+ writer.append("</id>");
+ }
+ }
+ if (deleteQ) {
+ for (String q : deleteQuery) {
+ writer.append("<query>");
+ XML.escapeCharData(q, writer);
+ writer.append("</query>");
+ }
+ }
+ writer.append("</delete>");
+ }
+ }
+
+ // --------------------------------------------------------------------------
+ // --------------------------------------------------------------------------
+
+ // --------------------------------------------------------------------------
+ //
+ // --------------------------------------------------------------------------
+
+ public List<SolrInputDocument> getDocuments() {
+ if (documents == null) return null;
+ List<SolrInputDocument> docs = new ArrayList<>(documents.size());
+ docs.addAll(documents.keySet());
+ return docs;
+ }
+
+ public Map<SolrInputDocument,Map<String,Object>> getDocumentsMap() {
+ return documents;
+ }
+
+ public Iterator<SolrInputDocument> getDocIterator() {
+ return docIterator;
+ }
+
+ public List<String> getDeleteById() {
+ if (deleteById == null) return null;
+ List<String> deletes = new ArrayList<>(deleteById.keySet());
+ return deletes;
+ }
+
+ public Map<String,Map<String,Object>> getDeleteByIdMap() {
+ return deleteById;
+ }
+
+ public List<String> getDeleteQuery() {
+ return deleteQuery;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/package-info.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/package-info.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/package-info.java
new file mode 100644
index 0000000..899a562
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/request/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Convenience classes for dealing with various types of Solr requests.
+ */
+package org.apache.solr.client.solrj.request;
+
+
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/AnalysisResponseBase.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/AnalysisResponseBase.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/AnalysisResponseBase.java
new file mode 100644
index 0000000..21396a5
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/AnalysisResponseBase.java
@@ -0,0 +1,252 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj.response;
+
+import org.apache.solr.common.util.NamedList;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A base class for all analysis responses.
+ *
+ *
+ * @since solr 1.4
+ */
+public class AnalysisResponseBase extends SolrResponseBase {
+
+ /**
+ * Parses the given named list and builds a list of analysis phases form it. Expects a named list of the form:
+ * <br>
+ * <pre><code>
+ * <lst name="index">
+ * <arr name="Tokenizer">
+ * <str name="text">the_text</str>
+ * <str name="rawText">the_raw_text</str> (optional)
+ * <str name="type">the_type</str>
+ * <int name="start">1</str>
+ * <int name="end">3</str>
+ * <int name="position">1</str>
+ * <bool name="match">true | false</bool> (optional)
+ * </arr>
+ * <arr name="Filter1">
+ * <str name="text">the_text</str>
+ * <str name="rawText">the_raw_text</str> (optional)
+ * <str name="type">the_type</str>
+ * <int name="start">1</str>
+ * <int name="end">3</str>
+ * <int name="position">1</str>
+ * <bool name="match">true | false</bool> (optional)
+ * </arr>
+ * ...
+ * </lst>
+ * </code></pre>
+ *
+ * @param phaseNL The names list to parse.
+ *
+ * @return The built analysis phases list.
+ */
+ protected List<AnalysisPhase> buildPhases(NamedList<List<NamedList<Object>>> phaseNL) {
+ List<AnalysisPhase> phases = new ArrayList<>(phaseNL.size());
+ for (Map.Entry<String, List<NamedList<Object>>> phaseEntry : phaseNL) {
+ AnalysisPhase phase = new AnalysisPhase(phaseEntry.getKey());
+ List<NamedList<Object>> tokens = phaseEntry.getValue();
+ for (NamedList<Object> token : tokens) {
+ TokenInfo tokenInfo = buildTokenInfo(token);
+ phase.addTokenInfo(tokenInfo);
+ }
+ phases.add(phase);
+ }
+ return phases;
+ }
+
+ /**
+ * Parses the given named list and builds a token infoform it. Expects a named list of the form:
+ * <br>
+ * <pre><code>
+ * <arr name="Tokenizer">
+ * <str name="text">the_text</str>
+ * <str name="rawText">the_raw_text</str> (optional)
+ * <str name="type">the_type</str>
+ * <int name="start">1</str>
+ * <int name="end">3</str>
+ * <int name="position">1</str>
+ * <bool name="match">true | false</bool> (optional)
+ * </arr>
+ * </code></pre>
+ *
+ * @param tokenNL The named list to parse.
+ *
+ * @return The built token info.
+ */
+ protected TokenInfo buildTokenInfo(NamedList<Object> tokenNL) {
+ String text = (String) tokenNL.get("text");
+ String rawText = (String) tokenNL.get("rawText");
+ String type = (String) tokenNL.get("type");
+ int start = (Integer) tokenNL.get("start");
+ int end = (Integer) tokenNL.get("end");
+ int position = (Integer) tokenNL.get("position");
+ Boolean match = (Boolean) tokenNL.get("match");
+ return new TokenInfo(text, rawText, type, start, end, position, (match == null ? false : match));
+ }
+
+
+ //================================================= Inner Classes ==================================================
+
+ /**
+ * A phase in the analysis process. The phase holds the tokens produced in this phase and the name of the class that
+ * produced them.
+ */
+ public static class AnalysisPhase {
+
+ private final String className;
+ private List<TokenInfo> tokens = new ArrayList<>();
+
+ AnalysisPhase(String className) {
+ this.className = className;
+ }
+
+ /**
+ * The name of the class (analyzer, tokenzier, or filter) that produced the token stream for this phase.
+ *
+ * @return The name of the class that produced the token stream for this phase.
+ */
+ public String getClassName() {
+ return className;
+ }
+
+ private void addTokenInfo(TokenInfo tokenInfo) {
+ tokens.add(tokenInfo);
+ }
+
+ /**
+ * Returns a list of tokens which represent the token stream produced in this phase.
+ *
+ * @return A list of tokens which represent the token stream produced in this phase.
+ */
+ public List<TokenInfo> getTokens() {
+ return tokens;
+ }
+
+ }
+
+ /**
+ * Holds all information of a token as part of an analysis phase.
+ */
+ public static class TokenInfo {
+
+ private final String text;
+ private final String rawText;
+ private final String type;
+ private final int start;
+ private final int end;
+ private final int position;
+ private final boolean match;
+
+ /**
+ * Constructs a new TokenInfo.
+ *
+ * @param text The text of the token
+ * @param rawText The raw text of the token. If the token is stored in the index in a special format (e.g.
+ * dates or padded numbers) this argument should hold this value. If the token is stored as is,
+ * then this value should be {@code null}.
+ * @param type The type fo the token (typically either {@code word} or {@code <ALPHANUM>} though it depends
+ * on the tokenizer/filter used).
+ * @param start The start position of the token in the original text where it was extracted from.
+ * @param end The end position of the token in the original text where it was extracted from.
+ * @param position The position of the token within the token stream.
+ * @param match Indicates whether this token matches one of the the query tokens.
+ */
+ TokenInfo(String text, String rawText, String type, int start, int end, int position, boolean match) {
+ this.text = text;
+ this.rawText = rawText;
+ this.type = type;
+ this.start = start;
+ this.end = end;
+ this.position = position;
+ this.match = match;
+ }
+
+ /**
+ * Returns the text of the token.
+ *
+ * @return The text of the token.
+ */
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * Returns the raw text of the token. If the token is index in a special format (e.g. date or paddded numbers)
+ * it will be returned as the raw text. Returns {@code null} if the token is indexed as is.
+ *
+ * @return Returns the raw text of the token.
+ */
+ public String getRawText() {
+ return rawText;
+ }
+
+ /**
+ * Returns the type of the token. Typically this will be {@code word} or {@code <ALPHANUM>}, but it really
+ * depends on the tokenizer and filters that are used.
+ *
+ * @return The type of the token.
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Returns the start position of this token within the text it was originally extracted from.
+ *
+ * @return The start position of this token within the text it was originally extracted from.
+ */
+ public int getStart() {
+ return start;
+ }
+
+ /**
+ * Returns the end position of this token within the text it was originally extracted from.
+ *
+ * @return The end position of this token within the text it was originally extracted from.
+ */
+ public int getEnd() {
+ return end;
+ }
+
+ /**
+ * Returns the position of this token within the produced token stream.
+ *
+ * @return The position of this token within the produced token stream.
+ */
+ public int getPosition() {
+ return position;
+ }
+
+ /**
+ * Returns whether this token matches one of the query tokens (if query analysis is performed).
+ *
+ * @return Whether this token matches one of the query tokens (if query analysis is performed).
+ */
+ public boolean isMatch() {
+ return match;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/CollectionAdminResponse.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/CollectionAdminResponse.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/CollectionAdminResponse.java
new file mode 100644
index 0000000..8acf2e2
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/CollectionAdminResponse.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj.response;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.solr.common.util.NamedList;
+
+public class CollectionAdminResponse extends SolrResponseBase
+{
+ @SuppressWarnings("unchecked")
+ public NamedList<NamedList<Object>> getCollectionStatus()
+ {
+ return (NamedList<NamedList<Object>>) getResponse().get( "success" );
+ }
+
+ public boolean isSuccess()
+ {
+ return getResponse().get( "success" ) != null;
+ }
+
+ // this messages are typically from individual nodes, since
+ // all the failures at the router are propagated as exceptions
+ @SuppressWarnings("unchecked")
+ public NamedList<String> getErrorMessages()
+ {
+ return (NamedList<String>) getResponse().get( "failure" );
+ }
+
+ @SuppressWarnings("unchecked")
+ public Map<String, NamedList<Integer>> getCollectionCoresStatus()
+ {
+ Map<String, NamedList<Integer>> res = new HashMap<>();
+ NamedList<NamedList<Object>> cols = getCollectionStatus();
+ if( cols != null ) {
+ for (Map.Entry<String, NamedList<Object>> e : cols) {
+ NamedList<Object> item = e.getValue();
+ String core = (String) item.get("core");
+ if (core != null) {
+ res.put(core, (NamedList<Integer>)item.get("responseHeader"));
+ }
+ }
+ }
+
+ return res;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Map<String, NamedList<Integer>> getCollectionNodesStatus()
+ {
+ Map<String, NamedList<Integer>> res = new HashMap<>();
+ NamedList<NamedList<Object>> cols = getCollectionStatus();
+ if( cols != null ) {
+ for (Map.Entry<String,NamedList<Object>> e : cols) {
+ if (e.getKey() != null) {
+ res.put(e.getKey(), (NamedList<Integer>) (e.getValue().get("responseHeader")));
+ }
+ }
+ }
+
+ return res;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/CoreAdminResponse.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/CoreAdminResponse.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/CoreAdminResponse.java
new file mode 100644
index 0000000..0492165
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/CoreAdminResponse.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj.response;
+
+import java.util.Date;
+import org.apache.solr.common.util.NamedList;
+
+/**
+ *
+ *
+ * @since solr 1.3
+ */
+public class CoreAdminResponse extends SolrResponseBase
+{
+ @SuppressWarnings("unchecked")
+ public NamedList<NamedList<Object>> getCoreStatus()
+ {
+ return (NamedList<NamedList<Object>>) getResponse().get( "status" );
+ }
+
+ public NamedList<Object> getCoreStatus( String core )
+ {
+ return getCoreStatus().get( core );
+ }
+
+ public Date getStartTime( String core )
+ {
+ NamedList<Object> v = getCoreStatus( core );
+ if( v == null ) {
+ return null;
+ }
+ return (Date) v.get( "startTime" );
+ }
+
+ public Long getUptime( String core )
+ {
+ NamedList<Object> v = getCoreStatus( core );
+ if( v == null ) {
+ return null;
+ }
+ return (Long) v.get( "uptime" );
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/DocumentAnalysisResponse.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/DocumentAnalysisResponse.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/DocumentAnalysisResponse.java
new file mode 100644
index 0000000..2f11d78
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/DocumentAnalysisResponse.java
@@ -0,0 +1,258 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj.response;
+
+import org.apache.solr.common.util.NamedList;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A response that is returned by processing the {@link org.apache.solr.client.solrj.request.DocumentAnalysisRequest}.
+ * Holds a map of {@link DocumentAnalysis} objects by a document id (unique key).
+ *
+ *
+ * @since solr 1.4
+ */
+public class DocumentAnalysisResponse extends AnalysisResponseBase implements Iterable<Map.Entry<String, DocumentAnalysisResponse.DocumentAnalysis>> {
+
+ private final Map<String, DocumentAnalysis> documentAnalysisByKey = new HashMap<>();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setResponse(NamedList<Object> response) {
+ super.setResponse(response);
+
+ @SuppressWarnings("unchecked")
+ NamedList<NamedList<NamedList<Object>>> analysis
+ = (NamedList<NamedList<NamedList<Object>>>) response.get("analysis");
+ for (Map.Entry<String, NamedList<NamedList<Object>>> document : analysis) {
+ DocumentAnalysis documentAnalysis = new DocumentAnalysis(document.getKey());
+ for (Map.Entry<String, NamedList<Object>> fieldEntry : document.getValue()) {
+ FieldAnalysis fieldAnalysis = new FieldAnalysis(fieldEntry.getKey());
+
+ NamedList<Object> field = fieldEntry.getValue();
+
+ @SuppressWarnings("unchecked")
+ NamedList<List<NamedList<Object>>> query
+ = (NamedList<List<NamedList<Object>>>) field.get("query");
+ if (query != null) {
+ List<AnalysisPhase> phases = buildPhases(query);
+ fieldAnalysis.setQueryPhases(phases);
+ }
+
+ @SuppressWarnings("unchecked")
+ NamedList<NamedList<List<NamedList<Object>>>> index
+ = (NamedList<NamedList<List<NamedList<Object>>>>) field.get("index");
+ for (Map.Entry<String, NamedList<List<NamedList<Object>>>> valueEntry : index) {
+ String fieldValue = valueEntry.getKey();
+ NamedList<List<NamedList<Object>>> valueNL = valueEntry.getValue();
+ List<AnalysisPhase> phases = buildPhases(valueNL);
+ fieldAnalysis.setIndexPhases(fieldValue, phases);
+ }
+
+ documentAnalysis.addFieldAnalysis(fieldAnalysis);
+ }
+
+ documentAnalysisByKey.put(documentAnalysis.getDocumentKey(), documentAnalysis);
+ }
+ }
+
+ /**
+ * Returns the number of document analyses in this response.
+ *
+ * @return The number of document analyses in this response.
+ */
+ public int getDocumentAnalysesCount() {
+ return documentAnalysisByKey.size();
+ }
+
+ /**
+ * Returns the document analysis for the document associated with the given unique key (id), {@code null} if no such
+ * association exists.
+ *
+ * @param documentKey The document unique key.
+ *
+ * @return The document analysis for the document associated with the given unique key (id).
+ */
+ public DocumentAnalysis getDocumentAnalysis(String documentKey) {
+ return documentAnalysisByKey.get(documentKey);
+ }
+
+ /**
+ * Returns an iterator over the document analyses map.
+ *
+ * @return An iterator over the document analyses map.
+ */
+ @Override
+ public Iterator<Map.Entry<String, DocumentAnalysis>> iterator() {
+ return documentAnalysisByKey.entrySet().iterator();
+ }
+
+ //================================================= Inner Classes ==================================================
+
+ /**
+ * An analysis process breakdown of a document. Holds a map of field analyses by the field name.
+ */
+ public static class DocumentAnalysis implements Iterable<Map.Entry<String, FieldAnalysis>> {
+
+ private final String documentKey;
+ private Map<String, FieldAnalysis> fieldAnalysisByFieldName = new HashMap<>();
+
+ private DocumentAnalysis(String documentKey) {
+ this.documentKey = documentKey;
+ }
+
+ private void addFieldAnalysis(FieldAnalysis fieldAnalysis) {
+ fieldAnalysisByFieldName.put(fieldAnalysis.getFieldName(), fieldAnalysis);
+ }
+
+ /**
+ * Returns the unique key of the analyzed document.
+ *
+ * @return The unique key of the analyzed document.
+ */
+ public String getDocumentKey() {
+ return documentKey;
+ }
+
+ /**
+ * Returns the number of field analyses for the documents.
+ *
+ * @return The number of field analyses for the documents.
+ */
+ public int getFieldAnalysesCount() {
+ return fieldAnalysisByFieldName.size();
+ }
+
+ public FieldAnalysis getFieldAnalysis(String fieldName) {
+ return fieldAnalysisByFieldName.get(fieldName);
+ }
+
+ /**
+ * Returns an iterator over the field analyses map.
+ *
+ * @return An iterator over the field analyses map.
+ */
+ @Override
+ public Iterator<Map.Entry<String, FieldAnalysis>> iterator() {
+ return fieldAnalysisByFieldName.entrySet().iterator();
+ }
+ }
+
+ /**
+ * An analysis process breakdown for a specific field. Holds a list of query time analysis phases (that is, if a
+ * query analysis was requested in the first place) and a list of index time analysis phases for each field value (a
+ * field can be multi-valued).
+ */
+ public static class FieldAnalysis {
+
+ private final String fieldName;
+ private List<AnalysisPhase> queryPhases;
+ private Map<String, List<AnalysisPhase>> indexPhasesByFieldValue = new HashMap<>();
+
+ private FieldAnalysis(String fieldName) {
+ this.fieldName = fieldName;
+ }
+
+ public void setQueryPhases(List<AnalysisPhase> queryPhases) {
+ this.queryPhases = queryPhases;
+ }
+
+ public void setIndexPhases(String fieldValue, List<AnalysisPhase> indexPhases) {
+ indexPhasesByFieldValue.put(fieldValue, indexPhases);
+ }
+
+ /**
+ * Returns the field name.
+ *
+ * @return The name of the field.
+ */
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ /**
+ * Returns the number of query time analysis phases or {@code -1} if
+ * this field analysis doesn't hold a query time analysis.
+ *
+ * @return Returns the number of query time analysis phases or {@code -1}
+ * if this field analysis doesn't hold a query time analysis.
+ */
+ public int getQueryPhasesCount() {
+ return queryPhases == null ? -1 : queryPhases.size();
+ }
+
+ /**
+ * Returns the query time analysis phases for the field or {@code null}
+ * if this field doesn't hold a query time analysis.
+ *
+ * @return Returns the query time analysis phases for the field or
+ * {@code null} if this field doesn't hold a query time analysis.
+ */
+ public Iterable<AnalysisPhase> getQueryPhases() {
+ return queryPhases;
+ }
+
+ /**
+ * Returns the number of values the field has.
+ *
+ * @return The number of values the field has.
+ */
+ public int getValueCount() {
+ return indexPhasesByFieldValue.entrySet().size();
+ }
+
+ /**
+ * Returns the number of index time analysis phases the given field value has.
+ *
+ * @param fieldValue The field value.
+ *
+ * @return The number of index time analysis phases the given field value has.
+ */
+ public int getIndexPhasesCount(String fieldValue) {
+ return indexPhasesByFieldValue.get(fieldValue).size();
+ }
+
+ /**
+ * Returns the index time analysis phases for the given field value.
+ *
+ * @param fieldValue The field value.
+ *
+ * @return The index time analysis phases for the given field value.
+ */
+ public Iterable<AnalysisPhase> getIndexPhases(String fieldValue) {
+ return indexPhasesByFieldValue.get(fieldValue);
+ }
+
+ /**
+ * Returns the index time analysis phases for all field values.
+ *
+ * @return Returns the index time analysis phases for all field value.
+ */
+ public Iterable<Map.Entry<String, List<AnalysisPhase>>> getIndexPhasesByFieldValue() {
+ return indexPhasesByFieldValue.entrySet();
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/FacetField.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/FacetField.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/FacetField.java
new file mode 100644
index 0000000..086c999
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/response/FacetField.java
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj.response;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.solr.client.solrj.util.ClientUtils;
+
+ /**
+ * A utility class to hold the facet response. It could use the NamedList container,
+ * but for JSTL, it is nice to have something that implements List so it can be iterated
+ *
+ * @since solr 1.3
+ */
+ public class FacetField implements Serializable
+ {
+ public static class Count implements Serializable
+ {
+ private String _name = null;
+ private long _count = 0;
+ // hang onto the FacetField for breadcrumb creation convenience
+ private FacetField _ff = null;
+
+ public Count( FacetField ff, String n, long c )
+ {
+ _name = n;
+ _count = c;
+ _ff = ff;
+ }
+
+ public String getName() {
+ return _name;
+ }
+
+ public void setName( String n )
+ {
+ _name = n;
+ }
+
+ public long getCount() {
+ return _count;
+ }
+
+ public void setCount( long c )
+ {
+ _count = c;
+ }
+
+ public FacetField getFacetField() {
+ return _ff;
+ }
+
+ @Override
+ public String toString()
+ {
+ return _name+" ("+_count+")";
+ }
+
+ public String getAsFilterQuery() {
+ if (_ff.getName().equals("facet_queries")) {
+ return _name;
+ }
+ return
+ ClientUtils.escapeQueryChars( _ff._name ) + ":" +
+ ClientUtils.escapeQueryChars( _name );
+ }
+ }
+
+ private String _name = null;
+ private List<Count> _values = null;
+ private String _gap = null;
+ private Date _end = null;
+
+ public FacetField( final String n )
+ {
+ _name = n;
+ }
+
+ public FacetField(String name, String gap, Date end) {
+ _name = name;
+ _gap = gap;
+ _end = end;
+ }
+
+ /**
+ * Date Gap Facet parameter
+ *
+ * @return the value specified for facet.date.gap
+ */
+ public String getGap() {
+ return _gap;
+ }
+
+ /**
+ * Date End Facet parameter
+ *
+ * @return the value specified for facet.date.end
+ */
+ public Date getEnd() {
+ return _end;
+ }
+
+ /**
+ * Insert at the end of the list
+ */
+ public void add( String name, long cnt )
+ {
+ if( _values == null ) {
+ _values = new ArrayList<>( 30 );
+ }
+ _values.add( new Count( this, name, cnt ) );
+ }
+
+ /**
+ * Insert at the beginning of the list.
+ */
+ public void insert( String name, long cnt )
+ {
+ if( _values == null ) {
+ _values = new ArrayList<>( 30 );
+ }
+ _values.add( 0, new Count( this, name, cnt ) );
+ }
+
+ public String getName() {
+ return _name;
+ }
+
+ public List<Count> getValues() {
+ return _values == null ? Collections.<Count>emptyList() : _values;
+ }
+
+ public int getValueCount()
+ {
+ return _values == null ? 0 : _values.size();
+ }
+
+ public FacetField getLimitingFields(long max)
+ {
+ FacetField ff = new FacetField( _name );
+ if( _values != null ) {
+ ff._values = new ArrayList<>( _values.size() );
+ for( Count c : _values ) {
+ if( c._count < max ) { // !equal to
+ ff._values.add( c );
+ }
+ }
+ }
+ return ff;
+ }
+
+ @Override
+ public String toString()
+ {
+ return _name + ":" + _values;
+ }
+ }