protected Property parse(String line, ValueFactories factories, PropertyFactory propFactory) { if (line.length() == 0) return null; // blank line char firstChar = line.charAt(0); if (firstChar == '#') return null; // comment line if (firstChar == ' ') return null; // ignore line Matcher matcher = PROPERTY_PATTERN.matcher(line); if (!matcher.matches()) { // It should be an empty multi-valued property, and the line consists only of the name ... Name name = factories.getNameFactory().create(decoder.decode(line)); return propFactory.create(name); } String nameString = decoder.decode(matcher.group(1)); String typeString = matcher.group(2); String valuesString = matcher.group(4); Name name = factories.getNameFactory().create(nameString); PropertyType type = PropertyType.valueFor(typeString); Pattern pattern = VALUE_PATTERN; ValueFactory<?> valueFactory = factories.getValueFactory(type); boolean binary = false; boolean decode = false; if (type == PropertyType.STRING) { // Parse the double-quoted value(s) ... pattern = STRING_VALUE_PATTERN; decode = true; } else if (type == PropertyType.BINARY) { binary = true; } Matcher valuesMatcher = pattern.matcher(valuesString); List<Object> values = new ArrayList<Object>(); while (valuesMatcher.find()) { String valueString = valuesMatcher.group(1); if (binary) { // The value is a hexadecimal-encoded byte array ... byte[] binaryValue = StringUtil.fromHexString(valueString); Object value = valueFactory.create(binaryValue); values.add(value); } else { if (decode) valueString = quoter.decode(valueString); Object value = valueFactory.create(valueString); values.add(value); } } if (values.isEmpty()) return null; return propFactory.create(name, type, values); }
/** * Find the existing node given the location. * * @param location the location of the node, which must have a {@link Location#getPath() path} * and/or {@link Location#getUuid() UUID} * @return the existing node; never null * @throws RepositoryException if there is an error working with the session * @throws PathNotFoundException if the node could not be found by its path */ public Node node(Location location) throws RepositoryException { Node root = session.getRootNode(); UUID uuid = location.getUuid(); if (uuid != null) { try { return session.getNodeByIdentifier(uuid.toString()); } catch (ItemNotFoundException e) { if (!location.hasPath()) { String msg = JcrConnectorI18n.unableToFindNodeWithUuid.text(getSourceName(), uuid); throw new PathNotFoundException( location, factories.getPathFactory().createRootPath(), msg); } // Otherwise, try to find it by its path ... } } if (location.hasPath()) { Path relativePath = location.getPath().relativeToRoot(); ValueFactory<String> stringFactory = factories.getStringFactory(); String relativePathStr = stringFactory.create(relativePath); try { return root.getNode(relativePathStr); } catch (javax.jcr.PathNotFoundException e) { // Figure out the lowest existing path ... Node node = root; for (Path.Segment segment : relativePath) { try { node = node.getNode(stringFactory.create(segment)); } catch (javax.jcr.PathNotFoundException e2) { String pathStr = stringFactory.create(location.getPath()); Path lowestPath = factories.getPathFactory().create(node.getPath()); throw new PathNotFoundException( location, lowestPath, JcrConnectorI18n.nodeDoesNotExist.text( getSourceName(), session.getWorkspace().getName(), pathStr)); } } } } // Otherwise, we can't find the node ... String msg = JcrConnectorI18n.unableToFindNodeWithoutPathOrUuid.text(getSourceName(), location); throw new IllegalArgumentException(msg); }
@SuppressWarnings("unchecked") private static <T> ValueFactory<T> getFactory( Map<PropertyType, ValueFactory<?>> factories, ValueFactory<T> defaultFactory) { PropertyType type = defaultFactory.getPropertyType(); ValueFactory<?> factory = factories.get(type); if (factory == null) { factory = defaultFactory; factories.put(type, factory); } return (ValueFactory<T>) factory; }
protected void write(Property property, Writer stream, ValueFactory<String> strings) throws IOException { String name = strings.create(property.getName()); stream.append(encoder.encode(name)); if (property.isEmpty()) return; stream.append(" ("); PropertyType type = PropertyType.discoverType(property.getFirstValue()); stream.append(type.getName().toLowerCase()); stream.append(") "); if (property.isMultiple()) { stream.append('['); } boolean first = true; boolean quote = type == PropertyType.STRING; for (Object value : property) { if (first) first = false; else stream.append(", "); String str = null; if (value instanceof Binary) { str = StringUtil.getHexString(((Binary) value).getBytes()); } else { str = strings.create(value); } if (quote) { stream.append('"'); stream.append(quoter.encode(str)); stream.append('"'); } else { stream.append(str); } } if (property.isMultiple()) { stream.append(']'); } stream.append('\n'); stream.flush(); }
/** * Fires the appropriate SAX events on the content handler to build the XML elements for the * property. * * @param propertyName the name of the property to be exported * @param propertyType the type of the property to be exported * @param value the value of the single-valued property to be exported * @param contentHandler the SAX content handler for which SAX events will be invoked as the XML * document is created. * @param skipBinary if <code>true</code>, indicates that binary properties should not be exported * @throws SAXException if an exception occurs during generation of the XML document * @throws RepositoryException if an exception occurs accessing the content repository */ private void emitProperty( Name propertyName, int propertyType, Object value, ContentHandler contentHandler, boolean skipBinary) throws RepositoryException, SAXException { ValueFactory<String> strings = session.getExecutionContext().getValueFactories().getStringFactory(); // first set the property sv:name attribute AttributesImpl propAtts = new AttributesImpl(); propAtts.addAttribute( JcrSvLexicon.NAME.getNamespaceUri(), JcrSvLexicon.NAME.getLocalName(), getPrefixedName(JcrSvLexicon.NAME), PropertyType.nameFromValue(PropertyType.STRING), strings.create(propertyName)); // and it's sv:type attribute propAtts.addAttribute( JcrSvLexicon.TYPE.getNamespaceUri(), JcrSvLexicon.TYPE.getLocalName(), getPrefixedName(JcrSvLexicon.TYPE), PropertyType.nameFromValue(PropertyType.STRING), PropertyType.nameFromValue(propertyType)); // output the sv:property element startElement(contentHandler, JcrSvLexicon.PROPERTY, propAtts); // then output a sv:value element for each of its values emitValue(strings.create(value), contentHandler); // end the sv:property element endElement(contentHandler, JcrSvLexicon.PROPERTY); }
protected String stringFor(Object value) { return stringFactory.create(value); }
/** * Create a standard set of value factories, using the supplied encoder/decoder. * * @param namespaceRegistry the namespace registry * @param decoder the decoder that should be used; if null, the {@link * ValueFactory#DEFAULT_DECODER default decoder} is used. * @param encoder the encoder that should be used; if null, the {@link * ValueFactory#DEFAULT_ENCODER default encoder} is used. * @param extraFactories any extra factories that should be used; any factory will override the * standard factories based upon the {@link ValueFactory#getPropertyType() factory's property * type}. * @throws IllegalArgumentException if the namespace registry is null */ public StandardValueFactories( NamespaceRegistry namespaceRegistry, TextDecoder decoder, TextEncoder encoder, ValueFactory<?>... extraFactories) { CheckArg.isNotNull(namespaceRegistry, "namespaceRegistry"); this.namespaceRegistry = namespaceRegistry; decoder = decoder != null ? decoder : ValueFactory.DEFAULT_DECODER; encoder = encoder != null ? encoder : ValueFactory.DEFAULT_ENCODER; Map<PropertyType, ValueFactory<?>> factories = new HashMap<PropertyType, ValueFactory<?>>(); // Put the extra factories into the map first ... for (ValueFactory<?> factory : extraFactories) { if (factory == null) continue; factories.put(factory.getPropertyType(), factory); } // Now assign the members, using the factories in the map or (if null) the supplied default ... this.stringFactory = getFactory(factories, new StringValueFactory(this.namespaceRegistry, decoder, encoder)); // The binary factory should NOT use the string factory that converts namespaces to prefixes ... StringValueFactory stringFactoryWithoutNamespaces = new StringValueFactory(decoder, encoder); this.binaryFactory = (BinaryFactory) getFactory( factories, new InMemoryBinaryValueFactory(decoder, stringFactoryWithoutNamespaces)); this.booleanFactory = getFactory(factories, new BooleanValueFactory(decoder, this.stringFactory)); this.dateFactory = (DateTimeFactory) getFactory(factories, new JodaDateTimeValueFactory(decoder, this.stringFactory)); this.decimalFactory = getFactory(factories, new DecimalValueFactory(decoder, this.stringFactory)); this.doubleFactory = getFactory(factories, new DoubleValueFactory(decoder, this.stringFactory)); this.longFactory = getFactory(factories, new LongValueFactory(decoder, this.stringFactory)); this.nameFactory = (NameFactory) getFactory( factories, new NameValueFactory(this.namespaceRegistry, decoder, this.stringFactory)); this.pathFactory = (PathFactory) getFactory( factories, new PathValueFactory(decoder, this.stringFactory, this.nameFactory)); this.referenceFactory = (ReferenceFactory) getFactory(factories, new ReferenceValueFactory(decoder, this.stringFactory, false)); this.weakReferenceFactory = (ReferenceFactory) getFactory(factories, new ReferenceValueFactory(decoder, this.stringFactory, true)); this.uuidFactory = (UuidFactory) getFactory(factories, new UuidValueFactory(decoder, this.stringFactory)); this.uriFactory = getFactory( factories, new UriValueFactory(this.namespaceRegistry, decoder, this.stringFactory)); this.objectFactory = getFactory( factories, new ObjectValueFactory(decoder, this.stringFactory, this.binaryFactory)); this.typeSystem = new ValueTypeSystem(this); }