Search in sources :

Example 11 with FieldSet

use of org.collectionspace.chain.csp.schema.FieldSet in project application by collectionspace.

the class GenericSearch method setRestricted.

/**
 * Pivots from the UI restriction concept to what the services needs. Initialises valriables if needed
 *
 * @param ui
 * @param param
 * @param pageNum
 * @param pageSize
 * @param search
 * @param r
 * @return
 * @throws UIException
 * @throws JSONException
 */
public static JSONObject setRestricted(UIRequest ui, String param, String pageNum, String pageSize, Boolean search, Record r) throws UIException, JSONException {
    JSONObject returndata = new JSONObject();
    JSONObject restriction = new JSONObject();
    String key = "results";
    if (param == null) {
        key = "items";
    }
    // restriction.put("pageNum","0"); //initialise
    Set<String> args = ui.getAllRequestArgument();
    for (String restrict : args) {
        if (!restrict.equals("_")) {
            if (ui.getRequestArgument(restrict) != null) {
                String value = ui.getRequestArgument(restrict);
                if (restrict.equals(WebMethod.SEARCH_QUERY_PARAM) && search) {
                    restrict = "keywords";
                    key = "results";
                }
                if (restrict.equals(WebMethod.PAGE_SIZE_PARAM) || restrict.equals(WebMethod.PAGE_NUM_PARAM) || restrict.equals(WebMethod.MARK_RELATED_QUERY_PARAM) || restrict.equals("keywords") || restrict.equals("sortDir")) {
                    restriction.put(restrict, value);
                } else if (restrict.equals("sortKey")) {
                    // //"summarylist.updatedAt"//movements_common:locationDate
                    if (r.isType("searchall")) {
                        log.debug("Ignoring sortKey (nor supported on searchall record):" + value);
                    } else {
                        String[] bits = value.split("\\.");
                        String fieldname = value;
                        if (bits.length > 1) {
                            fieldname = bits[1];
                        }
                        FieldSet fs = null;
                        if (fieldname.equals("number")) {
                            fs = r.getMiniNumber();
                        } else if (fieldname.equals("summary")) {
                            fs = r.getMiniSummary();
                        } else {
                            // convert sortKey
                            // CSPACE-4909: Getting null with fieldname = "movements_common:locationDate"
                            fs = r.getFieldFullList(fieldname);
                        }
                        if (fs == null) {
                            String msg = String.format("Undefined field name '%s' specified in query for '%s' records.", fieldname, r.whoamI);
                            UIException e = new UIException(msg);
                            log.error(msg, e);
                            throw e;
                        }
                        if (fs.hasMergeData()) {
                            // if this field is made up of multi merged fields in the UI then just pick the first field to sort on as services doesn't search on merged fields.
                            Field f = (Field) fs;
                            for (String fm : f.getAllMerge()) {
                                if (fm != null) {
                                    fs = r.getFieldFullList(fm);
                                    break;
                                }
                            }
                        }
                        fieldname = fs.getID();
                        String sortFieldname = r.getSortKey(fieldname);
                        if (StringUtils.isNotEmpty(sortFieldname)) {
                            log.debug("Found sort key " + sortFieldname + " for " + fieldname);
                            fs = r.getFieldFullList(sortFieldname);
                        }
                        // for debugging only
                        FieldSet tmp = fs;
                        fieldname = getSearchSpecifierForField(fs, true);
                        String tablebase = r.getServicesRecordPath(fs.getSection()).split(":", 2)[0];
                        String newvalue = tablebase + ":" + fieldname;
                        restriction.put(restrict, newvalue);
                    }
                } else if (restrict.equals("query")) {
                // ignore - someone was doing something odd
                } else {
                    // XXX I would so prefer not to restrict and just pass stuff up but I know it will cause issues later
                    restriction.put("queryTerm", restrict);
                    restriction.put("queryString", value);
                }
            }
        }
    }
    if (param != null && !param.equals("")) {
        restriction.put("queryTerm", "kw");
        restriction.put("queryString", param);
    // restriction.put(r.getDisplayNameField().getID(),param);
    }
    if (pageNum != null) {
        restriction.put("pageNum", pageNum);
    }
    if (pageSize != null) {
        restriction.put("pageSize", pageSize);
    }
    returndata.put("key", key);
    returndata.put("restriction", restriction);
    return returndata;
}
Also used : Field(org.collectionspace.chain.csp.schema.Field) FieldSet(org.collectionspace.chain.csp.schema.FieldSet) JSONObject(org.json.JSONObject) UIException(org.collectionspace.csp.api.ui.UIException)

Example 12 with FieldSet

use of org.collectionspace.chain.csp.schema.FieldSet in project application by collectionspace.

the class GenericSearch method buildQueryClauseForItem.

/**
 * @param r The current record spec we are searching on
 * @param fieldName The name of the field from UI (may have range suffix)
 * @param item The JSON object passed as the value
 * @param rangeSpecs a map of field-name to String-Pairs, specifying begin and end
 * @return
 * @throws JSONException
 */
private static String buildQueryClauseForItem(Record r, String fieldName, Object item, HashMap<String, RangeInfo> rangeSpecs) throws JSONException {
    log.debug("buildQueryClauseForItem: " + fieldName);
    boolean isRangeStart = false;
    boolean isRangeEnd = false;
    RangeInfo rangeInfo = null;
    String queryClause = "";
    if (fieldName.endsWith(Record.RANGE_START_SUFFIX)) {
        fieldName = fieldName.substring(0, (fieldName.length() - RANGE_START_SUFFIX_LEN));
        isRangeStart = true;
    } else if (fieldName.endsWith(Record.RANGE_END_SUFFIX)) {
        fieldName = fieldName.substring(0, (fieldName.length() - RANGE_END_SUFFIX_LEN));
        isRangeEnd = true;
    }
    if (isRangeStart || isRangeEnd) {
        rangeInfo = rangeSpecs.get(fieldName);
        if (rangeInfo == null)
            rangeInfo = new RangeInfo();
    }
    // FieldSet fieldSet = r.getSearchFieldFullList(fieldName); This seems like it shoudl work, but many fields are not in this map!
    FieldSet fieldSet = r.getFieldFullList(fieldName);
    if (fieldSet == null) {
        log.error("buildQueryClauseForItem: fieldName does not map to a FieldSet:" + fieldName);
        return queryClause;
    }
    String datatype = "";
    if (fieldSet instanceof Field) {
        datatype = ((Field) fieldSet).getDataType();
    }
    // do not want to build query term for the base entry field
    if (Field.QUERY_BEHAVIOR_IGNORE.equals(fieldSet.getQueryBehavior())) {
        log.error("buildQueryClauseForItem: QB_IGNORE on fieldName:" + fieldName);
        return queryClause;
    }
    if (item instanceof JSONArray || item instanceof JSONObject) {
        // Don't know how to handle this
        log.warn("GenericSearch.buildQuery ignoring unexpected field type for field: " + fieldName + " [" + item.getClass().getName() + "]");
    // Leave queryClause empty and fall through
    } else if (fieldSet.getUIType().equals("date")) {
        // UI returns String
        if (!(item instanceof String)) {
            log.error("GenericSearch.buildQuery field of type date not passed String value: " + fieldName + " / value is: [" + item.getClass().getName() + "]");
            return queryClause;
        }
        String value = (String) item;
        if (!value.isEmpty()) {
            value = utcToLocalTZ(value + TIMESTAMP_SUFFIX);
            if (isRangeStart) {
                rangeInfo.rangeStartValue = timeValToTimestampQueryString(value);
            } else if (isRangeEnd) {
                rangeInfo.rangeEndValue = timeValToTimestampQueryString(value);
            } else {
                // Straight equals a date. May not be used currently
                queryClause = getAdvancedSearch(r, fieldName, fieldSet, value, "\"", TIMESTAMP_CAST, EQUALS);
            }
            // Single field, not an interval
            if (rangeInfo != null) {
                if (rangeInfo.rangeStartOrSingleField == null) {
                    rangeInfo.rangeStartOrSingleField = getSchemaQualifiedSearchSpecifierForField(r, fieldName, fieldSet);
                    rangeInfo.rangeEndField = null;
                }
                rangeSpecs.put(fieldName, rangeInfo);
            // Leave queryClause empty and fall through
            }
        }
    } else if (fieldSet.getUIType().equals("groupfield/structureddate")) {
        // UI returns String
        if (!(item instanceof String)) {
            log.error("GenericSearch.buildQuery field of type structured date not passed String value: " + fieldName + " / value is: [" + item.getClass().getName() + "]");
            return queryClause;
        }
        String value = (String) item;
        if (!value.isEmpty()) {
            value = utcToLocalTZ(value + TIMESTAMP_SUFFIX);
            if (isRangeStart) {
                rangeInfo.rangeStartValue = timeValToTimestampQueryString(value);
            } else if (isRangeEnd) {
                rangeInfo.rangeEndValue = timeValToTimestampQueryString(value);
            } else {
                // Cannot do direct compare on structured date.
                log.error("GenericSearch.buildQuery field of type structured date not passed Range value: " + fieldName);
                return queryClause;
            }
            // Specify interval values
            if (rangeInfo != null) {
                if (rangeInfo.rangeStartOrSingleField == null) {
                    String searchSpec = getSchemaQualifiedSearchSpecifierForField(r, fieldName, fieldSet);
                    rangeInfo.rangeStartOrSingleField = searchSpec + "/dateEarliestScalarValue";
                    rangeInfo.rangeEndField = searchSpec + "/dateLatestScalarValue";
                }
                rangeSpecs.put(fieldName, rangeInfo);
            // Leave queryClause empty and fall through
            }
        }
    } else if (datatype.equals(FieldSet.DATATYPE_BOOLEAN)) {
        Boolean value = null;
        if (item instanceof String) {
            String valueString = (String) item;
            if (!valueString.isEmpty()) {
                value = Boolean.parseBoolean((String) item);
            }
        } else if (item instanceof Boolean) {
            value = (Boolean) item;
        } else {
            log.error("GenericSearch.buildQuery field of type boolean not passed boolean or string value: " + fieldName);
        }
        if (value != null) {
            queryClause = "(" + getSchemaQualifiedSearchSpecifierForField(r, fieldName, fieldSet) + (value ? " = 1" : " = 0") + ")";
        }
    } else if (item instanceof String) {
        // Includes fields of types String, int, float, authRefs
        String value = (String) item;
        String wrapChar = getQueryValueWrapChar(fieldSet);
        if (!value.isEmpty()) {
            if (isRangeStart) {
                rangeInfo.rangeStartValue = wrapChar + value + wrapChar;
            } else if (isRangeEnd) {
                rangeInfo.rangeEndValue = wrapChar + value + wrapChar;
            } else {
                queryClause = getAdvancedSearch(r, fieldName, fieldSet, value, getQueryValueWrapChar(fieldSet), "", ILIKE_COMPARATOR);
            }
            // These fields are all single - no intervals on basic fields
            if (rangeInfo != null) {
                if (rangeInfo.rangeStartOrSingleField == null) {
                    rangeInfo.rangeStartOrSingleField = getSchemaQualifiedSearchSpecifierForField(r, fieldName, fieldSet);
                    rangeInfo.rangeEndField = null;
                }
                rangeSpecs.put(fieldName, rangeInfo);
            // Leave queryClause empty and fall through
            }
        }
    } else if (item instanceof Boolean) {
        boolean value = ((Boolean) item).booleanValue();
        queryClause = "(" + getSchemaQualifiedSearchSpecifierForField(r, fieldName, fieldSet) + (value ? " = 1" : " = 0") + ")";
    }
    return queryClause;
}
Also used : Field(org.collectionspace.chain.csp.schema.Field) FieldSet(org.collectionspace.chain.csp.schema.FieldSet) JSONObject(org.json.JSONObject) JSONArray(org.json.JSONArray)

Example 13 with FieldSet

use of org.collectionspace.chain.csp.schema.FieldSet in project application by collectionspace.

the class WebAutoComplete method doAuthorityAutocomplete.

private JSONArray doAuthorityAutocomplete(CSPRequestCache cache, Storage storage, String fieldname, String start, String vocabConstraint, String pageSize, String pageNum) throws JSONException, ExistException, UnimplementedException, UnderlyingStorageException, ConfigException {
    FieldSet fs = r.getFieldFullList(fieldname);
    JSONArray out = new JSONArray();
    Instance[] allInstances = null;
    if (fs == null || !(fs instanceof Field)) {
        if (r.hasHierarchyUsed("screen")) {
            // Configures the hierarchy section.
            Structure s = r.getStructure("screen");
            if (s.hasOption(fieldname)) {
                // This is one of the hierarchy fields
                if (vocabConstraint != null) {
                    allInstances = new Instance[1];
                    String fullname = r.getID() + "-" + vocabConstraint;
                    allInstances[0] = r.getSpec().getInstance(fullname);
                } else {
                    Option a = s.getOption(fieldname);
                    String[] data = a.getName().split(",");
                    allInstances = new Instance[data.length];
                    for (int i = 0; i < data.length; i++) {
                        allInstances[i] = (r.getSpec().getInstance(data[i]));
                    }
                }
            } else {
                fs = r.getSpec().getRecord("hierarchy").getFieldFullList(fieldname);
                if (fs instanceof Field) {
                    allInstances = ((Field) fs).getAllAutocompleteInstances();
                }
            }
        }
    } else {
        allInstances = ((Field) fs).getAllAutocompleteInstances();
    }
    if (allInstances == null) {
        // Cannot autocomplete
        return out;
    }
    // support multiassign of autocomplete instances
    for (Instance n : allInstances) {
        try {
            if (n == null) {
            // Field has no autocomplete
            } else {
                String path = n.getRecord().getID() + "/" + n.getTitleRef();
                JSONObject restriction = new JSONObject();
                if (pageSize != null) {
                    restriction.put("pageSize", pageSize);
                }
                if (pageNum != null) {
                    restriction.put("pageNum", pageNum);
                }
                FieldSet dispNameFS = n.getRecord().getDisplayNameField();
                if (dispNameFS == null) {
                    throw new ConfigException("WebAutoComplete for Instance has no displayName configured: " + n.getID());
                }
                String displayNameFieldID = dispNameFS.getID();
                // May be something other than display name
                restriction.put(displayNameFieldID, start);
                JSONObject results = storage.getPathsJSON(path, restriction);
                String[] paths = (String[]) results.get("listItems");
                for (String csid : paths) {
                    JSONObject data = storage.retrieveJSON(path + "/" + csid + "/view", new JSONObject());
                    JSONObject entry = new JSONObject();
                    // TODO - handle multiple name matches
                    String displayNameString = data.getString(displayNameFieldID);
                    JSONArray displayNames = JSONUtils.createJSONArrayFromSeparatedString(displayNameString);
                    String primaryDN = displayNames.getString(0);
                    String refid = data.getString("refid");
                    // HACK - transition period with full instead of base URN value
                    if (refid.endsWith("'" + primaryDN + "'"))
                        refid = refid.substring(0, refid.length() - (primaryDN.length() + 2));
                    entry.put("baseUrn", refid);
                    entry.put("csid", data.getString("csid"));
                    entry.put("type", n.getRecord().getWebURL());
                    entry.put("displayNames", displayNames);
                    // RefName.AuthorityItem item = RefName.AuthorityItem.parse(refid);
                    // entry.put("namespace",item.getParentShortIdentifier());
                    entry.put("namespace", data.getString("namespace"));
                    entry.put("workflow", data.getString("workflow"));
                    out.put(entry);
                }
            }
        } catch (UnderlyingStorageException x) {
            if (x.getStatus() == 403) {
            // permission error - keep calm and carry on
            } else {
                throw x;
            }
        }
    }
    // Instance n=((Field)fs).getAutocompleteInstance();
    return out;
}
Also used : Instance(org.collectionspace.chain.csp.schema.Instance) JSONArray(org.json.JSONArray) ConfigException(org.collectionspace.chain.csp.config.ConfigException) UnderlyingStorageException(org.collectionspace.csp.api.persistence.UnderlyingStorageException) Field(org.collectionspace.chain.csp.schema.Field) FieldSet(org.collectionspace.chain.csp.schema.FieldSet) JSONObject(org.json.JSONObject) Option(org.collectionspace.chain.csp.schema.Option) Structure(org.collectionspace.chain.csp.schema.Structure)

Example 14 with FieldSet

use of org.collectionspace.chain.csp.schema.FieldSet in project application by collectionspace.

the class WebAutoComplete method doRecordAutocomplete.

/**
 * Handles autocomplete for non-authority records. Simpler model that does not involve
 * multiple namespaces (a.k.a., vocabs, a.k.a., Instances).
 * @param cache
 * @param storage
 * @param fieldname Should generally only be one of broader* or narrower*
 * @param start The partial string to match
 * @param pageSize
 * @param pageNum
 * @return the JSON output payload of results.
 * @throws JSONException
 * @throws ExistException
 * @throws UnimplementedException
 * @throws UnderlyingStorageException
 * @throws ConfigException
 */
private JSONArray doRecordAutocomplete(CSPRequestCache cache, Storage storage, String fieldname, String start, String pageSize, String pageNum) throws JSONException, ExistException, UnimplementedException, UnderlyingStorageException, ConfigException {
    // FieldSet fs=r.getFieldFullList(fieldname); we do not really care, frankly
    JSONArray out = new JSONArray();
    JSONObject restriction = new JSONObject();
    if (pageSize != null) {
        restriction.put("pageSize", pageSize);
    }
    if (pageNum != null) {
        restriction.put("pageNum", pageNum);
    }
    FieldSet dispNameFS = r.getDisplayNameField();
    if (dispNameFS == null) {
        throw new ConfigException("WebAutoComplete for record has no displayName configured: " + r.getID());
    }
    String displayNameFieldID = dispNameFS.getID();
    // May be something other than display name
    restriction.put(displayNameFieldID, start);
    String path = r.getID();
    JSONObject results = storage.getPathsJSON(path, restriction);
    String[] paths = (String[]) results.get("listItems");
    for (String csid : paths) {
        // Appending the "list" to the path will glean the "list" marked fields, into a "summarylist"
        JSONObject data = storage.retrieveJSON(path + "/" + csid + "/view/list", new JSONObject());
        JSONObject entry = new JSONObject();
        JSONObject summarylist = data.getJSONObject("summarylist");
        String displayNameString = summarylist.getString(displayNameFieldID);
        String refName = summarylist.getString("refName");
        // Build a base refName without trailing displayName suffix
        if (refName.endsWith("'" + displayNameString + "'"))
            refName = refName.substring(0, refName.length() - (displayNameString.length() + 2));
        entry.put("baseUrn", refName);
        entry.put("csid", summarylist.getString("csid"));
        entry.put("type", r.getWebURL());
        // Standard temCompletion widget handles arrays of alternate terms, so
        // we pass an array for consistency.
        JSONArray displayNames = new JSONArray();
        displayNames.put(displayNameString);
        entry.put("displayNames", displayNames);
        out.put(entry);
    }
    return out;
}
Also used : FieldSet(org.collectionspace.chain.csp.schema.FieldSet) JSONObject(org.json.JSONObject) JSONArray(org.json.JSONArray) ConfigException(org.collectionspace.chain.csp.config.ConfigException)

Example 15 with FieldSet

use of org.collectionspace.chain.csp.schema.FieldSet in project application by collectionspace.

the class MakeXsd method generateRepeat.

private void generateRepeat(Repeat repeatField, Element fieldElement, String listName, Namespace ns, Element root) throws Exception {
    if (repeatField.hasServicesParent() && !repeatField.hasOrphans()) {
        // for example, <repeat id="assocPersonGroupList/assocPersonGroup"> where the left side of the '/' is the services parent
        Element sequenced = null;
        int pathCount = 0;
        for (String path : repeatField.getServicesParent()) {
            if (path != null) {
                Element ele = root.addElement(new QName("complexType", ns));
                ele.addAttribute("name", path);
                sequenced = ele.addElement(new QName("sequence", ns));
                pathCount++;
            }
            if (log.isDebugEnabled() == true && pathCount > 1) {
                // pathCount should never be > 1
                sendToDebugLog("Service parent path count is: " + pathCount);
            }
        }
        if (sequenced != null) {
            Element dele = sequenced.addElement(new QName("element", ns));
            String servicesTag = repeatField.getServicesTag();
            dele.addAttribute("name", servicesTag);
            String servicesType = repeatField.getServicesType();
            if (servicesType == null) {
                // If the type was not explicitly set in the config, then use the servicesTag as the type
                servicesType = servicesTag;
            }
            dele.addAttribute("type", FieldSet.NS + servicesType);
            dele.addAttribute("minOccurs", "0");
            dele.addAttribute("maxOccurs", "unbounded");
        }
    }
    // 
    // If there was no explicitly declared service type, then we may need to define one.
    // 
    String servicesType = repeatField.getServicesType();
    if (servicesType == null) {
        // Create the "complexType" node
        Element ele = fieldElement.addElement(new QName("complexType", ns));
        servicesType = listName;
        if (repeatField.hasServicesParent() == true && repeatField.hasOrphans() == true) {
            // If orphaned, we use the first half of the "foo/bar" id attribute tuple -i.e., the parent type
            servicesType = repeatField.getServicesParent()[0];
        }
        boolean definedNewType = false;
        if (servicesType != null) {
            ele.addAttribute("name", servicesType);
            definedNewType = true;
        } else {
            sendToDebugLog("Created an anonymous complex type for Repeat ID=" + repeatField.getID());
        }
        // Now create a "sequence" node and iterate over the children items of the Repeat instance
        Element sele = ele.addElement(new QName("sequence", ns));
        for (FieldSet fs : repeatField.getChildren("")) {
            generateDataEntry(sele, fs, ns, root, isUnbounded(fs));
        }
        if (definedNewType == true) {
            String complextTypeXSD = ele.asXML();
            if (isValidNewType(servicesType, complextTypeXSD, repeatField.getID()) == true) {
                if (isDefinedLocally(servicesType, complextTypeXSD) == true) {
                    // No need to define this type more than once in the current schema, so remove the element we just created.
                    fieldElement.remove(ele);
                } else {
                    recordDefinedComplexTypes.put(servicesType, complextTypeXSD);
                    String msg = String.format("Defined new complex type '%s': %s", servicesType != null ? servicesType : listName, complextTypeXSD);
                    sendToDebugLog(msg);
                }
            }
        }
    } else {
        sendToDebugLog(String.format("Creating repeat element with existing service type '%s'", servicesType));
    }
}
Also used : FieldSet(org.collectionspace.chain.csp.schema.FieldSet) QName(org.dom4j.QName) Element(org.dom4j.Element)

Aggregations

FieldSet (org.collectionspace.chain.csp.schema.FieldSet)62 JSONObject (org.json.JSONObject)36 Record (org.collectionspace.chain.csp.schema.Record)23 Field (org.collectionspace.chain.csp.schema.Field)22 JSONArray (org.json.JSONArray)22 Element (org.dom4j.Element)19 Group (org.collectionspace.chain.csp.schema.Group)17 UnderlyingStorageException (org.collectionspace.csp.api.persistence.UnderlyingStorageException)17 JSONException (org.json.JSONException)13 Repeat (org.collectionspace.chain.csp.schema.Repeat)11 Document (org.dom4j.Document)11 QName (org.dom4j.QName)11 ConnectionException (org.collectionspace.chain.csp.persistence.services.connection.ConnectionException)10 ReturnedDocument (org.collectionspace.chain.csp.persistence.services.connection.ReturnedDocument)9 ReturnedMultipartDocument (org.collectionspace.chain.csp.persistence.services.connection.ReturnedMultipartDocument)8 UnsupportedEncodingException (java.io.UnsupportedEncodingException)7 ArrayList (java.util.ArrayList)6 UnimplementedException (org.collectionspace.csp.api.persistence.UnimplementedException)6 TenantSpec (org.collectionspace.chain.csp.persistence.services.TenantSpec)5 Spec (org.collectionspace.chain.csp.schema.Spec)5