/** * Load schema. * * @param schema the schema * @param schemaElement the schema element * @return the map * @throws Exception the exception */ @SuppressWarnings("unchecked") private static Map<String, Object> loadSchema( Schema schema, org.dom4j.Element schemaElement, ServiceContext ctx) throws Exception { String schemaName1 = schemaElement.attributeValue( ExportConstants.NAME_ATTR); // FIXME: Do we need this local var? String schemaName = schema.getName(); Map<String, Object> data = new HashMap<String, Object>(); Iterator<org.dom4j.Element> it = schemaElement.elementIterator(); while (it.hasNext()) { org.dom4j.Element element = it.next(); String name = element.getName(); Field field = schema.getField(name); if (field != null) { Object value = getElementData(element, field.getType(), ctx); data.put(name, value); } else { // FIXME: substitute an appropriate constant for "csid" below. // One potential class to which to add that constant, if it is not already // declared, might be AbstractCollectionSpaceResourceImpl - ADR 2012-09-24 if (!name.equals("csid")) { // 'csid' elements in input payloads can be safely ignored. logger.warn( "Invalid input document. No such property was found [" + name + "] in schema " + schemaName); } } } return data; }
// called from XSDLoader protected void registerSchema(Schema schema) { schemas.put(schema.getName(), schema); Namespace ns = schema.getNamespace(); uriToSchema.put(ns.uri, schema); if (!StringUtils.isBlank(ns.prefix)) { prefixToSchema.put(ns.prefix, schema); } }
@Override public Field getField(String xpath) { checkDirty(); Field field = null; if (xpath != null && xpath.contains("/")) { // need to resolve subfields String[] properties = xpath.split("/"); Field resolvedField = getField(properties[0]); for (int x = 1; x < properties.length; x++) { if (resolvedField == null) { break; } resolvedField = getField(resolvedField, properties[x], x == properties.length - 1); } if (resolvedField != null) { field = resolvedField; } } else { field = fields.get(xpath); if (field == null) { QName qname = QName.valueOf(xpath); String prefix = qname.getPrefix(); Schema schema = getSchemaFromPrefix(prefix); if (schema == null) { // try using the name schema = getSchema(prefix); } if (schema != null) { field = schema.getField(qname.getLocalName()); if (field != null) { // map is concurrent so parallelism is ok fields.put(xpath, field); } } } } return field; }
/** * Builds the document. * * @param document the document * @param e the e * @param objectProps the object props * @throws Exception the exception */ public static void buildDocument( Document document, Element parent, Map<String, Object> objectProps, Schema schema) throws Exception { for (String prop : objectProps.keySet()) { Object value = objectProps.get(prop); if (value != null) { Field field = schema.getField(prop); // If there is no field, then we added this property to the properties, // and it must be a String (e.g., CSID) // TODO - infer the type from the type of Object, if we need more than String if (field == null) { field = new FieldImpl(new QName(prop), schema, StringType.INSTANCE); } buildProperty(document, parent, field, value); } } }
/** * @return The message if it's found in message bundles, a generic message otherwise. * @since 7.1 */ public String getMessage(Locale locale) { // test whether there's a specific translation for for this field and this constraint // the expected key is // label.schema.constraint.violation.[constraintName].[schemaName].[field].[subField] List<String> pathTokens = new ArrayList<String>(); pathTokens.add(Constraint.MESSAGES_KEY); pathTokens.add(constraint.getDescription().getName()); pathTokens.add(schema.getName()); for (PathNode node : path) { String name = node.getField().getName().getLocalName(); pathTokens.add(name); } String key = StringUtils.join(pathTokens, '.'); String computedInvalidValue = "null"; if (invalidValue != null) { String invalidValueString = invalidValue.toString(); if (invalidValueString.length() > 20) { computedInvalidValue = invalidValueString.substring(0, 15) + "..."; } else { computedInvalidValue = invalidValueString; } } Object[] params = new Object[] {computedInvalidValue}; Locale computedLocale = locale != null ? locale : Constraint.MESSAGES_DEFAULT_LANG; String message = null; try { message = I18NUtils.getMessageString(Constraint.MESSAGES_BUNDLE, key, params, computedLocale); } catch (MissingResourceException e) { log.trace("No bundle found", e); message = null; } if (message != null && !message.trim().isEmpty() && !key.equals(message)) { // use the message if there's one return message; } else { if (locale != null && Locale.ENGLISH.getLanguage().equals(locale.getLanguage())) { // use the constraint message return constraint.getErrorMessage(invalidValue, locale); } else { return getMessage(Locale.ENGLISH); } } }
/** Recomputes all the info needed for efficient access. */ private void recomputeSourceInfos() throws DirectoryException { final Schema schema = schemaManager.getSchema(schemaName); if (schema == null) { throw new DirectoryException( String.format("Directory '%s' has unknown schema '%s'", directory.getName(), schemaName)); } final Set<String> sourceFields = new HashSet<String>(); for (Field f : schema.getFields()) { sourceFields.add(f.getName().getLocalName()); } if (!sourceFields.contains(schemaIdField)) { throw new DirectoryException( String.format( "Directory '%s' schema '%s' has no id field '%s'", directory.getName(), schemaName, schemaIdField)); } List<SourceInfo> newSourceInfos = new ArrayList<SourceInfo>(2); for (SourceDescriptor source : descriptor.sources) { int ndirs = source.subDirectories.length; if (ndirs == 0) { throw new DirectoryException( String.format( "Directory '%s' source '%s' has no subdirectories", directory.getName(), source.name)); } final List<SubDirectoryInfo> subDirectoryInfos = new ArrayList<SubDirectoryInfo>(ndirs); SubDirectoryInfo authDirectoryInfo = null; boolean hasRequiredDir = false; for (SubDirectoryDescriptor subDir : source.subDirectories) { final String dirName = subDir.name; final String dirSchemaName = directoryService.getDirectorySchema(dirName); final String dirIdField = directoryService.getDirectoryIdField(dirName); final boolean dirIsAuth = directoryService.getDirectoryPasswordField(dirName) != null; final Map<String, String> fromSource = new HashMap<String, String>(); final Map<String, String> toSource = new HashMap<String, String>(); final Map<String, Serializable> defaultEntry = new HashMap<String, Serializable>(); final boolean dirIsOptional = subDir.isOptional; // XXX check authenticating final Schema dirSchema = schemaManager.getSchema(dirSchemaName); if (dirSchema == null) { throw new DirectoryException( String.format( "Directory '%s' source '%s' subdirectory '%s' " + "has unknown schema '%s'", directory.getName(), source.name, dirName, dirSchemaName)); } // record default field mappings if same name and record default // values final Set<String> dirSchemaFields = new HashSet<String>(); for (Field f : dirSchema.getFields()) { final String fieldName = f.getName().getLocalName(); dirSchemaFields.add(fieldName); if (sourceFields.contains(fieldName)) { // XXX check no duplicates! fromSource.put(fieldName, fieldName); toSource.put(fieldName, fieldName); } // XXX cast to Serializable defaultEntry.put(fieldName, (Serializable) f.getDefaultValue()); } // treat renamings // XXX id field ? for (FieldDescriptor field : subDir.fields) { final String sourceFieldName = field.forField; final String fieldName = field.name; if (!sourceFields.contains(sourceFieldName)) { throw new DirectoryException( String.format( "Directory '%s' source '%s' subdirectory '%s' " + "has mapping for unknown field '%s'", directory.getName(), source.name, dirName, sourceFieldName)); } if (!dirSchemaFields.contains(fieldName)) { throw new DirectoryException( String.format( "Directory '%s' source '%s' subdirectory '%s' " + "has mapping of unknown field' '%s'", directory.getName(), source.name, dirName, fieldName)); } fromSource.put(sourceFieldName, fieldName); toSource.put(fieldName, sourceFieldName); } SubDirectoryInfo subDirectoryInfo = new SubDirectoryInfo( dirName, dirSchemaName, dirIdField, dirIsAuth, fromSource, toSource, defaultEntry, dirIsOptional); subDirectoryInfos.add(subDirectoryInfo); if (dirIsAuth) { if (authDirectoryInfo != null) { throw new DirectoryException( String.format( "Directory '%s' source '%s' has two subdirectories " + "with a password field, '%s' and '%s'", directory.getName(), source.name, authDirectoryInfo.dirName, dirName)); } authDirectoryInfo = subDirectoryInfo; } if (!dirIsOptional) { hasRequiredDir = true; } } if (isAuthenticating() && authDirectoryInfo == null) { throw new DirectoryException( String.format( "Directory '%s' source '%s' has no subdirectory " + "with a password field", directory.getName(), source.name)); } if (!hasRequiredDir) { throw new DirectoryException( String.format( "Directory '%s' source '%s' only has optional subdirectories: " + "no directory can be used has a reference.", directory.getName(), source.name)); } newSourceInfos.add(new SourceInfo(source, subDirectoryInfos, authDirectoryInfo)); } sourceInfos = newSourceInfos; }
/** Sets a value (may be complex/list) into the document at the given xpath. */ protected void setValueObject(T state, String xpath, Object value) throws PropertyException { xpath = canonicalXPath(xpath); String[] segments = xpath.split("/"); ComplexType parentType = getType(); for (int i = 0; i < segments.length; i++) { String segment = segments[i]; Field field = parentType.getField(segment); if (field == null && i == 0) { // check facets SchemaManager schemaManager = Framework.getService(SchemaManager.class); for (String facet : getFacets()) { CompositeType facetType = schemaManager.getFacet(facet); field = facetType.getField(segment); if (field != null) { break; } } } if (field == null && i == 0 && getProxySchemas() != null) { // check proxy schemas for (Schema schema : getProxySchemas()) { field = schema.getField(segment); if (field != null) { break; } } } if (field == null) { throw new PropertyNotFoundException(xpath, i == 0 ? null : "Unknown segment: " + segment); } String name = field.getName().getPrefixedName(); // normalize from segment Type type = field.getType(); // check if we have a complex list index in the next position if (i < segments.length - 1 && StringUtils.isNumeric(segments[i + 1])) { int index = Integer.parseInt(segments[i + 1]); i++; if (!type.isListType() || ((ListType) type).getFieldType().isSimpleType()) { throw new PropertyNotFoundException(xpath, "Cannot use index after segment: " + segment); } List<T> list = getChildAsList(state, name); if (index >= list.size()) { throw new PropertyNotFoundException(xpath, "Index out of bounds: " + index); } // find complex list state state = list.get(index); field = ((ListType) type).getField(); if (i == segments.length - 1) { // last segment setValueComplex(state, field, value); } else { // not last segment parentType = (ComplexType) field.getType(); } continue; } if (i == segments.length - 1) { // last segment setValueField(state, field, value); } else { // not last segment if (type.isSimpleType()) { // scalar throw new PropertyNotFoundException(xpath, "Segment must be last: " + segment); } else if (type.isComplexType()) { // complex property state = getChildForWrite(state, name, type); parentType = (ComplexType) type; } else { // list ListType listType = (ListType) type; if (listType.isArray()) { // array of scalars throw new PropertyNotFoundException(xpath, "Segment must be last: " + segment); } else { // complex list but next segment was not numeric throw new PropertyNotFoundException( xpath, "Missing list index after segment: " + segment); } } } } }
/** Gets a value (may be complex/list) from the document at the given xpath. */ protected Object getValueObject(T state, String xpath) throws PropertyException { xpath = canonicalXPath(xpath); String[] segments = xpath.split("/"); /* * During this loop state may become null if we read an uninitialized complex property (DBS), in that case the * code must treat it as reading uninitialized values for its children. */ ComplexType parentType = getType(); for (int i = 0; i < segments.length; i++) { String segment = segments[i]; Field field = parentType.getField(segment); if (field == null && i == 0) { // check facets SchemaManager schemaManager = Framework.getService(SchemaManager.class); for (String facet : getFacets()) { CompositeType facetType = schemaManager.getFacet(facet); field = facetType.getField(segment); if (field != null) { break; } } } if (field == null && i == 0 && getProxySchemas() != null) { // check proxy schemas for (Schema schema : getProxySchemas()) { field = schema.getField(segment); if (field != null) { break; } } } if (field == null) { throw new PropertyNotFoundException(xpath, i == 0 ? null : "Unknown segment: " + segment); } String name = field.getName().getPrefixedName(); // normalize from segment Type type = field.getType(); // check if we have a complex list index in the next position if (i < segments.length - 1 && StringUtils.isNumeric(segments[i + 1])) { int index = Integer.parseInt(segments[i + 1]); i++; if (!type.isListType() || ((ListType) type).getFieldType().isSimpleType()) { throw new PropertyNotFoundException(xpath, "Cannot use index after segment: " + segment); } List<T> list = state == null ? Collections.emptyList() : getChildAsList(state, name); if (index >= list.size()) { throw new PropertyNotFoundException(xpath, "Index out of bounds: " + index); } // find complex list state state = list.get(index); parentType = (ComplexType) ((ListType) type).getFieldType(); if (i == segments.length - 1) { // last segment return getValueComplex(state, parentType); } else { // not last segment continue; } } if (i == segments.length - 1) { // last segment return state == null ? null : getValueField(state, field); } else { // not last segment if (type.isSimpleType()) { // scalar throw new PropertyNotFoundException(xpath, "Segment must be last: " + segment); } else if (type.isComplexType()) { // complex property state = state == null ? null : getChild(state, name, type); // here state can be null (DBS), continue loop with it, meaning uninitialized for read parentType = (ComplexType) type; } else { // list ListType listType = (ListType) type; if (listType.isArray()) { // array of scalars throw new PropertyNotFoundException(xpath, "Segment must be last: " + segment); } else { // complex list but next segment was not numeric throw new PropertyNotFoundException( xpath, "Missing list index after segment: " + segment); } } } } throw new AssertionError("not reached"); }