You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ho...@apache.org on 2017/05/10 21:42:29 UTC

[08/50] [abbrv] lucene-solr:jira/solr-10290: SOLR-10647: Move the V1 <-> V2 API mapping to SolrJ

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0184d6b7/solr/solrj/src/java/org/apache/solr/common/util/CommandOperation.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/common/util/CommandOperation.java b/solr/solrj/src/java/org/apache/solr/common/util/CommandOperation.java
new file mode 100644
index 0000000..5b043e7
--- /dev/null
+++ b/solr/solrj/src/java/org/apache/solr/common/util/CommandOperation.java
@@ -0,0 +1,318 @@
+/*
+ * 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.common.util;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.solr.common.SolrException;
+import org.noggit.JSONParser;
+import org.noggit.ObjectBuilder;
+
+import static java.util.Collections.emptyMap;
+import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
+import static org.apache.solr.common.util.StrUtils.formatString;
+import static org.apache.solr.common.util.Utils.toJSON;
+
+public class CommandOperation {
+  public final String name;
+  private Object commandData;//this is most often a map
+  private List<String> errors = new ArrayList<>();
+
+  public CommandOperation(String operationName, Object metaData) {
+    commandData = metaData;
+    this.name = operationName;
+  }
+
+  public Object getCommandData() {
+    return commandData;
+  }
+
+  public String getStr(String key, String def) {
+    if (ROOT_OBJ.equals(key)) {
+      Object obj = getRootPrimitive();
+      return obj == def ? null : String.valueOf(obj);
+    }
+    Object o = getMapVal(key);
+    return o == null ? def : String.valueOf(o);
+  }
+
+  public boolean getBoolean(String key, boolean def) {
+    String v = getStr(key,null);
+    return v == null? def:Boolean.parseBoolean(v);
+  }
+  public void setCommandData(Object o){
+    commandData = o;
+  }
+
+  public Map<String,Object> getDataMap() {
+    if (commandData instanceof Map) {
+      //noinspection unchecked
+      return (Map<String,Object>)commandData;
+    }
+    addError(StrUtils.formatString("The command ''{0}'' should have the values as a json object {key:val} format", name));
+    return Collections.emptyMap();
+  }
+
+  private Object getRootPrimitive() {
+    if (commandData instanceof Map) {
+      errors.add(StrUtils.formatString("The value has to be a string for command : ''{0}'' ", name));
+      return null;
+    }
+    return commandData;
+
+  }
+
+  public Object getVal(String key) {
+    return getMapVal(key);
+  }
+
+  private Object getMapVal(String key) {
+    if("".equals(key)){
+      if (commandData instanceof Map) {
+        addError("value of the command is an object should be primitive");
+      }
+      return commandData;
+    }
+    if (commandData instanceof Map) {
+      Map metaData = (Map) commandData;
+      return metaData.get(key);
+    } else {
+      String msg = " value has to be an object for operation :" + name;
+      if (!errors.contains(msg)) errors.add(msg);
+      return null;
+    }
+  }
+
+  public List<String> getStrs(String key) {
+    List<String> val = getStrs(key, null);
+    if (val == null) {
+      errors.add(StrUtils.formatString(REQD, key));
+    }
+    return val;
+
+  }
+
+  public void unknownOperation() {
+    addError(formatString("Unknown operation ''{0}'' ", name));
+  }
+
+  static final String REQD = "''{0}'' is a required field";
+
+
+  /**
+   * Get collection of values for a key. If only one val is present a
+   * single value collection is returned
+   */
+  public List<String> getStrs(String key, List<String> def) {
+    Object v = null;
+    if (ROOT_OBJ.equals(key)) {
+      v = getRootPrimitive();
+    } else {
+      v = getMapVal(key);
+    }
+    if (v == null) {
+      return def;
+    } else {
+      if (v instanceof List) {
+        ArrayList<String> l = new ArrayList<>();
+        for (Object o : (List) v) {
+          l.add(String.valueOf(o));
+        }
+        if (l.isEmpty()) return def;
+        return l;
+      } else {
+        return singletonList(String.valueOf(v));
+      }
+    }
+
+  }
+
+  /**
+   * Get a required field. If missing it adds to the errors
+   */
+  public String getStr(String key) {
+    if (ROOT_OBJ.equals(key)) {
+      Object obj = getRootPrimitive();
+      if (obj == null) {
+        errors.add(StrUtils.formatString(REQD, name));
+      }
+      return obj == null ? null : String.valueOf(obj);
+    }
+
+    String s = getStr(key, null);
+    if (s == null) errors.add(StrUtils.formatString(REQD, key));
+    return s;
+  }
+
+  private Map errorDetails() {
+    return Utils.makeMap(name, commandData, ERR_MSGS, errors);
+  }
+
+  public boolean hasError() {
+    return !errors.isEmpty();
+  }
+
+  public void addError(String s) {
+    if (errors.contains(s)) return;
+    errors.add(s);
+  }
+
+  /**
+   * Get all the values from the metadata for the command
+   * without the specified keys
+   */
+  public Map<String,Object> getValuesExcluding(String... keys) {
+    getMapVal(null);
+    if (hasError()) return emptyMap();//just to verify the type is Map
+    @SuppressWarnings("unchecked") 
+    LinkedHashMap<String, Object> cp = new LinkedHashMap<>((Map<String, Object>) commandData);
+    if (keys == null) return cp;
+    for (String key : keys) {
+      cp.remove(key);
+    }
+    return cp;
+  }
+
+
+  public List<String> getErrors() {
+    return errors;
+  }
+
+  public static final String ERR_MSGS = "errorMessages";
+  public static final String ROOT_OBJ = "";
+
+  public static List<Map> captureErrors(List<CommandOperation> ops) {
+    List<Map> errors = new ArrayList<>();
+    for (CommandOperation op : ops) {
+      if (op.hasError()) {
+        errors.add(op.errorDetails());
+      }
+    }
+    return errors;
+  }
+
+
+  /**
+   * Parse the command operations into command objects
+   */
+  public static List<CommandOperation> parse(Reader rdr) throws IOException {
+    JSONParser parser = new JSONParser(rdr);
+
+    ObjectBuilder ob = new ObjectBuilder(parser);
+
+    if (parser.lastEvent() != JSONParser.OBJECT_START) {
+      throw new RuntimeException("The JSON must be an Object of the form {\"command\": {...},...");
+    }
+    List<CommandOperation> operations = new ArrayList<>();
+    for (; ; ) {
+      int ev = parser.nextEvent();
+      if (ev == JSONParser.OBJECT_END) return operations;
+      Object key = ob.getKey();
+      ev = parser.nextEvent();
+      Object val = ob.getVal();
+      if (val instanceof List) {
+        List list = (List) val;
+        for (Object o : list) {
+          if (!(o instanceof Map)) {
+            operations.add(new CommandOperation(String.valueOf(key), list));
+            break;
+          } else {
+            operations.add(new CommandOperation(String.valueOf(key), o));
+          }
+        }
+      } else {
+        operations.add(new CommandOperation(String.valueOf(key), val));
+      }
+    }
+
+  }
+
+  public CommandOperation getCopy() {
+    return new CommandOperation(name, commandData);
+  }
+
+  public Map getMap(String key, Map def) {
+    Object o = getMapVal(key);
+    if (o == null) return def;
+    if (!(o instanceof Map)) {
+      addError(StrUtils.formatString("''{0}'' must be a map", key));
+      return def;
+    } else {
+      return (Map) o;
+
+    }
+  }
+
+  @Override
+  public String toString() {
+    return new String(toJSON(singletonMap(name, commandData)), StandardCharsets.UTF_8);
+  }
+
+  public static List<CommandOperation> readCommands(Iterable<ContentStream> streams, NamedList resp)
+      throws IOException {
+    if (streams == null) {
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "missing content stream");
+    }
+    ArrayList<CommandOperation> ops = new ArrayList<>();
+
+    for (ContentStream stream : streams)
+      ops.addAll(parse(stream.getReader()));
+    List<Map> errList = CommandOperation.captureErrors(ops);
+    if (!errList.isEmpty()) {
+      resp.add(CommandOperation.ERR_MSGS, errList);
+      return null;
+    }
+    return ops;
+  }
+
+  public static List<CommandOperation> clone(List<CommandOperation> ops) {
+    List<CommandOperation> opsCopy = new ArrayList<>(ops.size());
+    for (CommandOperation op : ops) opsCopy.add(op.getCopy());
+    return opsCopy;
+  }
+
+
+  public Integer getInt(String name, Integer def) {
+    Object o = getVal(name);
+    if (o == null) return def;
+    if (o instanceof Number) {
+      Number number = (Number) o;
+      return number.intValue();
+    } else {
+      try {
+        return Integer.parseInt(o.toString());
+      } catch (NumberFormatException e) {
+        addError(StrUtils.formatString("{0} is not a valid integer", name));
+        return null;
+      }
+    }
+  }
+
+  public Integer getInt(String name) {
+    Object o = getVal(name);
+    if(o == null) return null;
+    return getInt(name, null);
+  }
+}