private String[] parseDerefParts(Element fieldEl, String valueExpr) throws IndexerConfException { // // Split, normalize, validate the input // String[] derefParts = valueExpr.split(Pattern.quote("=>")); for (int i = 0; i < derefParts.length; i++) { String trimmed = derefParts[i].trim(); if (trimmed.length() == 0) { throw new IndexerConfException( "Invalid dereference expression '" + valueExpr + "' at " + LocationAttributes.getLocationString(fieldEl)); } derefParts[i] = trimmed; } if (derefParts.length < 2) { throw new IndexerConfException( "Invalid dereference expression '" + valueExpr + "' at " + LocationAttributes.getLocationString(fieldEl)); } return derefParts; }
private Value buildValue(Element fieldEl) throws Exception { String valueExpr = DocumentHelper.getAttribute(fieldEl, "value", true); Value value; boolean extractContent = DocumentHelper.getBooleanAttribute(fieldEl, "extractContent", false); String formatter = DocumentHelper.getAttribute(fieldEl, "formatter", false); if (formatter != null && !conf.getFormatters().hasFormatter(formatter)) { throw new IndexerConfException( "Formatter does not exist: " + formatter + " at " + LocationAttributes.getLocationString(fieldEl)); } // // An index field can basically map to two kinds of values: // * plain field values // * dereference expressions (following links to some other record and then taking a field // value from it) // // A dereference expression is specified as "somelink=>somelink=>somefield" if (valueExpr.contains("=>")) { // // A dereference field // value = buildDerefValue(fieldEl, valueExpr, extractContent, formatter); } else { // // A plain field // value = new FieldValue(getFieldType(valueExpr, fieldEl), extractContent, formatter); } if (extractContent && !value .getTargetFieldType() .getValueType() .getDeepestValueType() .getBaseName() .equals("BLOB")) { throw new IndexerConfException( "extractContent is used for a non-blob value at " + LocationAttributes.getLocation(fieldEl)); } return value; }
private void processLessDimensionedVariantsDeref( Element fieldEl, String valueExpr, DerefValue deref, String derefPart) throws IndexerConfException { // The variant dimensions are specified in a syntax like "-var1,-var2,-var3" boolean validConfig = true; Set<String> dimensions = new HashSet<String>(); for (String op : COMMA_SPLITTER.split(derefPart)) { if (op.length() > 1 && op.startsWith("-")) { String dimension = op.substring(1); dimensions.add(dimension); } else { validConfig = false; break; } } if (dimensions.size() == 0) validConfig = false; if (!validConfig) { throw new IndexerConfException( "Invalid specification of variants to follow: '" + derefPart + "', deref expression: '" + valueExpr + "' " + "at " + LocationAttributes.getLocation(fieldEl)); } deref.addVariantFollow(dimensions); }
private boolean processFieldDeref( Element fieldEl, String valueExpr, DerefValue deref, String derefPart) throws IndexerConfException, InterruptedException, RepositoryException { boolean lastFollowIsRecord; FieldType followField = getFieldType(derefPart, fieldEl); String type = followField.getValueType().getBaseName(); if (type.equals("LIST")) { type = followField.getValueType().getNestedValueType().getBaseName(); } if (type.equals("RECORD")) { deref.addRecordFieldFollow(followField); lastFollowIsRecord = true; } else if (type.equals("LINK")) { deref.addLinkFieldFollow(followField); lastFollowIsRecord = false; } else { throw new IndexerConfException( "Dereferencing is not possible on field of type " + followField.getValueType().getName() + ". Field: '" + derefPart + "', deref expression '" + valueExpr + "' at " + LocationAttributes.getLocation(fieldEl)); } return lastFollowIsRecord; }
private Map<String, String> parseVariantPropertiesPattern(Element caseEl) throws Exception { String variant = DocumentHelper.getAttribute(caseEl, "matchVariant", false); Map<String, String> varPropsPattern = new HashMap<String, String>(); if (variant == null) return varPropsPattern; for (String prop : COMMA_SPLITTER.split(variant)) { int eqPos = prop.indexOf("="); if (eqPos != -1) { String propName = prop.substring(0, eqPos); String propValue = prop.substring(eqPos + 1); if (propName.equals("*")) { throw new IndexerConfException( String.format( "Error in matchVariant attribute: the character '*' " + "can only be used as wildcard, not as variant dimension name, attribute = %1$s, at: %2$s", variant, LocationAttributes.getLocation(caseEl))); } varPropsPattern.put(propName, propValue); } else { varPropsPattern.put(prop, null); } } return varPropsPattern; }
private void processMoreDimensionedVariantsDeref( Element fieldEl, String valueExpr, DerefValue deref, String derefPart) throws IndexerConfException { // The variant dimension is specified in a syntax like "+var1=boo,+var2" boolean validConfig = true; Map<String, String> dimensions = new HashMap<String, String>(); for (String op : COMMA_SPLITTER.split(derefPart)) { if (op.length() > 1 && op.startsWith("+")) { final Iterator<String> keyAndValue = EQUAL_SIGN_SPLITTER.split(op).iterator(); if (keyAndValue.hasNext()) { final String key = keyAndValue.next().substring(1); // ignore leading '+' if (keyAndValue.hasNext()) { // there is an equal sign -> key and value final String value = keyAndValue.next(); dimensions.put(key, value); } else { // no equal sign -> only key without value dimensions.put(key, null); } } else { // nothing at all? validConfig = false; break; } } else { validConfig = false; break; } } if (dimensions.size() == 0) validConfig = false; if (!validConfig) { throw new IndexerConfException( "Invalid specification of variants to follow: '" + derefPart + "', deref expression: '" + valueExpr + "' " + "at " + LocationAttributes.getLocation(fieldEl)); } deref.addForwardVariantFollow(dimensions); }
private FieldType constructDerefFieldType(Element fieldEl, String valueExpr, String[] derefParts) throws IndexerConfException, InterruptedException, RepositoryException { // // Last element in the list should be a field // QName targetFieldName; try { targetFieldName = parseQName(derefParts[derefParts.length - 1], fieldEl); } catch (IndexerConfException e) { throw new IndexerConfException( "Dereference expression does not end on a valid field name. " + "Expression: '" + valueExpr + "' at " + LocationAttributes.getLocationString(fieldEl), e); } return getFieldType(targetFieldName); }
private Value buildDerefValue( Element fieldEl, String valueExpr, boolean extractContent, String formatter) throws IndexerConfException, InterruptedException, RepositoryException { final String[] derefParts = parseDerefParts(fieldEl, valueExpr); final FieldType fieldType = constructDerefFieldType(fieldEl, valueExpr, derefParts); final DerefValue deref = new DerefValue(fieldType, extractContent, formatter); // // Run over all children except the last // boolean lastFollowIsRecord = false; for (int i = 0; i < derefParts.length - 1; i++) { String derefPart = derefParts[i]; // A deref expression can navigate through 5 kinds of 'links': // - a link stored in a link field (detected based on presence of a colon) // - a nested record // - a link to the master variant (if it's the literal string 'master') // - a link to a less-dimensioned variant // - a link to a more-dimensioned variant if (derefPart.contains(":")) { // It's a field name lastFollowIsRecord = processFieldDeref(fieldEl, valueExpr, deref, derefPart); } else if (derefPart.equals("master")) { // Link to master variant if (lastFollowIsRecord) { throw new IndexerConfException( "In dereferencing, master cannot follow on record-type field." + " Deref expression: '" + valueExpr + "' at " + LocationAttributes.getLocation(fieldEl)); } lastFollowIsRecord = false; deref.addMasterFollow(); } else if (derefPart.trim().startsWith("-")) { // Link to less dimensioned variant if (lastFollowIsRecord) { throw new IndexerConfException( "In dereferencing, variant cannot follow on record-type field." + " Deref expression: '" + valueExpr + "' at " + LocationAttributes.getLocation(fieldEl)); } lastFollowIsRecord = false; processLessDimensionedVariantsDeref(fieldEl, valueExpr, deref, derefPart); } else if (derefPart.trim().startsWith("+")) { // Link to more dimensioned variant if (lastFollowIsRecord) { throw new IndexerConfException( "In dereferencing, variant cannot follow on record-type field." + " Deref expression: '" + valueExpr + "' at " + LocationAttributes.getLocation(fieldEl)); } lastFollowIsRecord = false; processMoreDimensionedVariantsDeref(fieldEl, valueExpr, deref, derefPart); } } deref.init(typeManager); return deref; }
private void buildDynamicFields() throws Exception { List<Element> fields = DYNAMIC_INDEX_FIELDS.get().evalAsNativeElementList(doc); for (Element fieldEl : fields) { String matchNamespaceAttr = DocumentHelper.getAttribute(fieldEl, "matchNamespace", false); String matchNameAttr = DocumentHelper.getAttribute(fieldEl, "matchName", false); String matchTypeAttr = DocumentHelper.getAttribute(fieldEl, "matchType", false); String matchScopeAttr = DocumentHelper.getAttribute(fieldEl, "matchScope", false); String nameAttr = DocumentHelper.getAttribute(fieldEl, "name", true); WildcardPattern matchNamespace = null; if (matchNamespaceAttr != null) { // If the matchNamespace attr does not contain a wildcard expression, and its value // happens to be an existing namespace prefix, than substitute the prefix for the full URI. if (!WildcardPattern.isWildcardExpression(matchNamespaceAttr)) { String uri = fieldEl.lookupNamespaceURI(matchNamespaceAttr); if (uri != null) matchNamespaceAttr = uri; } matchNamespace = new WildcardPattern(matchNamespaceAttr); } WildcardPattern matchName = null; if (matchNameAttr != null) { matchName = new WildcardPattern(matchNameAttr); } TypePattern matchTypes = null; if (matchTypeAttr != null) { matchTypes = new TypePattern(matchTypeAttr); } Set<Scope> matchScopes = null; if (matchScopeAttr != null) { matchScopes = EnumSet.noneOf(Scope.class); for (String scope : COMMA_SPLITTER.split(matchScopeAttr)) { matchScopes.add(Scope.valueOf(scope)); } if (matchScopes.isEmpty()) { matchScopes = null; } } // Be gentle to users of Lily 1.0 and warn them about attributes that are not supported // anymore if (DocumentHelper.getAttribute(fieldEl, "matchMultiValue", false) != null) { log.warn( "The attribute matchMultiValue on dynamicField is not supported anymore, it will be ignored."); } if (DocumentHelper.getAttribute(fieldEl, "matchHierarchical", false) != null) { log.warn( "The attribute matchHierarchical on dynamicField is not supported anymore, it will be ignored."); } Set<String> variables = new HashSet<String>(); variables.add("namespace"); variables.add("name"); variables.add("type"); variables.add("baseType"); variables.add("nestedType"); variables.add("nestedBaseType"); variables.add("deepestNestedBaseType"); if (matchName != null && matchName.hasWildcard()) variables.add("nameMatch"); if (matchNamespace != null && matchNamespace.hasWildcard()) variables.add("namespaceMatch"); Set<String> booleanVariables = new HashSet<String>(); booleanVariables.add("list"); booleanVariables.add("multiValue"); NameTemplate name = new NameTemplate(nameAttr, variables, booleanVariables); boolean extractContent = DocumentHelper.getBooleanAttribute(fieldEl, "extractContent", false); String formatter = DocumentHelper.getAttribute(fieldEl, "formatter", false); if (formatter != null && !conf.getFormatters().hasFormatter(formatter)) { throw new IndexerConfException( "Formatter does not exist: " + formatter + " at " + LocationAttributes.getLocationString(fieldEl)); } boolean continue_ = DocumentHelper.getBooleanAttribute(fieldEl, "continue", false); DynamicIndexField field = new DynamicIndexField( matchNamespace, matchName, matchTypes, matchScopes, name, extractContent, continue_, formatter); conf.addDynamicIndexField(field); } }