001    /*
002     * JBoss DNA (http://www.jboss.org/dna)
003     * See the COPYRIGHT.txt file distributed with this work for information
004     * regarding copyright ownership.  Some portions may be licensed
005     * to Red Hat, Inc. under one or more contributor license agreements.
006    * See the AUTHORS.txt file in the distribution for a full listing of 
007    * individual contributors.
008     *
009     * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010     * is licensed to you under the terms of the GNU Lesser General Public License as
011     * published by the Free Software Foundation; either version 2.1 of
012     * the License, or (at your option) any later version.
013     *
014     * JBoss DNA is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     * Lesser General Public License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this software; if not, write to the Free
021     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023     */
024    package org.jboss.dna.graph.property.basic;
025    
026    import java.io.InputStream;
027    import java.io.Reader;
028    import java.math.BigDecimal;
029    import java.net.URI;
030    import java.util.ArrayList;
031    import java.util.Calendar;
032    import java.util.Date;
033    import java.util.LinkedList;
034    import java.util.List;
035    import java.util.UUID;
036    import java.util.regex.Pattern;
037    import net.jcip.annotations.Immutable;
038    import org.jboss.dna.common.text.TextDecoder;
039    import org.jboss.dna.common.util.CheckArg;
040    import org.jboss.dna.graph.GraphI18n;
041    import org.jboss.dna.graph.property.Binary;
042    import org.jboss.dna.graph.property.DateTime;
043    import org.jboss.dna.graph.property.IoException;
044    import org.jboss.dna.graph.property.Name;
045    import org.jboss.dna.graph.property.Path;
046    import org.jboss.dna.graph.property.PathFactory;
047    import org.jboss.dna.graph.property.PropertyType;
048    import org.jboss.dna.graph.property.Reference;
049    import org.jboss.dna.graph.property.ValueFactory;
050    import org.jboss.dna.graph.property.ValueFormatException;
051    import org.jboss.dna.graph.property.Path.Segment;
052    
053    /**
054     * The standard {@link ValueFactory} for {@link PropertyType#NAME} values.
055     * 
056     * @author Randall Hauch
057     * @author John Verhaeg
058     */
059    @Immutable
060    public class PathValueFactory extends AbstractValueFactory<Path> implements PathFactory {
061    
062        /**
063         * Regular expression used to identify the different segments in a path, using the standard '/' delimiter. The expression is
064         * simply:
065         * 
066         * <pre>
067         * /
068         * </pre>
069         */
070        protected static final Pattern DELIMITER_PATTERN = Pattern.compile("/");
071    
072        /**
073         * Regular expression used to identify the different parts of a segment. The expression is
074         * 
075         * <pre>
076         * ([&circ;*:/\[\]|]+)(:([&circ;*:/\[\]|]+))?(\[(\d+)])?
077         * </pre>
078         * 
079         * where the first part is accessed with group 1, the second part is accessed with group 3, and the index is accessed with
080         * group 5.
081         */
082        protected static final Pattern SEGMENT_PATTERN = Pattern.compile("([^:/]+)(:([^/\\[\\]]+))?(\\[(\\d+)])?");
083    
084        private final ValueFactory<Name> nameValueFactory;
085    
086        public PathValueFactory( TextDecoder decoder,
087                                 ValueFactory<String> stringValueFactory,
088                                 ValueFactory<Name> nameValueFactory ) {
089            super(PropertyType.PATH, decoder, stringValueFactory);
090            CheckArg.isNotNull(nameValueFactory, "nameValueFactory");
091            this.nameValueFactory = nameValueFactory;
092        }
093    
094        /**
095         * @return nameValueFactory
096         */
097        protected ValueFactory<Name> getNameValueFactory() {
098            return this.nameValueFactory;
099        }
100    
101        /**
102         * <p>
103         * {@inheritDoc}
104         * </p>
105         * 
106         * @see org.jboss.dna.graph.property.PathFactory#createRootPath()
107         */
108        public Path createRootPath() {
109            return RootPath.INSTANCE;
110        }
111    
112        /**
113         * {@inheritDoc}
114         */
115        public Path create( String value ) {
116            return create(value, getDecoder());
117        }
118    
119        /**
120         * {@inheritDoc}
121         */
122        public Path create( final String value,
123                            TextDecoder decoder ) {
124            if (value == null) return null;
125            String trimmedValue = value.trim();
126            int length = trimmedValue.length();
127            boolean absolute = false;
128            if (length == 0) {
129                return BasicPath.EMPTY_RELATIVE;
130            }
131            if (Path.DELIMITER_STR.equals(trimmedValue)) return RootPath.INSTANCE;
132            if (Path.SELF.equals(trimmedValue)) return BasicPath.SELF_PATH;
133            if (Path.PARENT.equals(trimmedValue)) return BasicPath.PARENT_PATH;
134    
135            // Remove the leading delimiter ...
136            if (trimmedValue.charAt(0) == Path.DELIMITER) {
137                trimmedValue = length > 1 ? trimmedValue.substring(1) : "";
138                --length;
139                absolute = true;
140            }
141            // remove the trailing delimiter ...
142            if (length > 0 && trimmedValue.charAt(length - 1) == Path.DELIMITER) {
143                trimmedValue = length > 1 ? trimmedValue.substring(0, length - 1) : "";
144                length = trimmedValue.length();
145            }
146            if (length == 0) {
147                return RootPath.INSTANCE;
148            }
149    
150            // Parse the path into its segments ...
151            List<Segment> segments = new ArrayList<Segment>();
152            String[] pathSegments = DELIMITER_PATTERN.split(trimmedValue);
153            if (pathSegments.length == 0) {
154                throw new ValueFormatException(value, getPropertyType(), GraphI18n.validPathMayNotContainEmptySegment.text(value));
155            }
156            if (decoder == null) decoder = getDecoder();
157            assert pathSegments.length != 0;
158            assert decoder != null;
159            for (String segment : pathSegments) {
160                assert segment != null;
161                segment = segment.trim();
162                if (segment.length() == 0) {
163                    throw new ValueFormatException(value, getPropertyType(), GraphI18n.validPathMayNotContainEmptySegment.text(value));
164                }
165                // Create the name and add a segment with it ...
166                segments.add(createSegment(segment, decoder));
167            }
168    
169            if (absolute && segments.size() == 1) {
170                // Special case of a single-segment name ...
171                return new ChildPath(RootPath.INSTANCE, segments.get(0));
172            }
173            // Create a path constructed from the supplied segments ...
174            return new BasicPath(segments, absolute);
175        }
176    
177        /**
178         * {@inheritDoc}
179         */
180        public Path create( int value ) {
181            throw new ValueFormatException(value, getPropertyType(),
182                                           GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
183                                                                              Integer.class.getSimpleName(),
184                                                                              value));
185        }
186    
187        /**
188         * {@inheritDoc}
189         */
190        public Path create( long value ) {
191            throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
192                                                                                                        Long.class.getSimpleName(),
193                                                                                                        value));
194        }
195    
196        /**
197         * {@inheritDoc}
198         */
199        public Path create( boolean value ) {
200            throw new ValueFormatException(value, getPropertyType(),
201                                           GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
202                                                                              Boolean.class.getSimpleName(),
203                                                                              value));
204        }
205    
206        /**
207         * {@inheritDoc}
208         */
209        public Path create( float value ) {
210            throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
211                                                                                                        Float.class.getSimpleName(),
212                                                                                                        value));
213        }
214    
215        /**
216         * {@inheritDoc}
217         */
218        public Path create( double value ) {
219            throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
220                                                                                                        Double.class.getSimpleName(),
221                                                                                                        value));
222        }
223    
224        /**
225         * {@inheritDoc}
226         */
227        public Path create( BigDecimal value ) {
228            throw new ValueFormatException(value, getPropertyType(),
229                                           GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
230                                                                              BigDecimal.class.getSimpleName(),
231                                                                              value));
232        }
233    
234        /**
235         * {@inheritDoc}
236         */
237        public Path create( Calendar value ) {
238            throw new ValueFormatException(value, getPropertyType(),
239                                           GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
240                                                                              Calendar.class.getSimpleName(),
241                                                                              value));
242        }
243    
244        /**
245         * {@inheritDoc}
246         */
247        public Path create( Date value ) {
248            throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
249                                                                                                        Date.class.getSimpleName(),
250                                                                                                        value));
251        }
252    
253        /**
254         * {@inheritDoc}
255         * 
256         * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.DateTime)
257         */
258        public Path create( DateTime value ) throws ValueFormatException {
259            throw new ValueFormatException(value, getPropertyType(),
260                                           GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
261                                                                              DateTime.class.getSimpleName(),
262                                                                              value));
263        }
264    
265        /**
266         * {@inheritDoc}
267         */
268        public Path create( Name value ) {
269            if (value == null) return null;
270            try {
271                return new ChildPath(RootPath.INSTANCE, new BasicPathSegment(value));
272            } catch (IllegalArgumentException e) {
273                throw new ValueFormatException(value, getPropertyType(), e);
274            }
275        }
276    
277        /**
278         * {@inheritDoc}
279         */
280        public Path create( Path value ) {
281            return value;
282        }
283    
284        /**
285         * {@inheritDoc}
286         */
287        public Path createAbsolutePath( Name... segmentNames ) {
288            if (segmentNames == null || segmentNames.length == 0) return RootPath.INSTANCE;
289            List<Segment> segments = new ArrayList<Segment>(segmentNames.length);
290            for (Name segmentName : segmentNames) {
291                if (segmentName == null) {
292                    CheckArg.containsNoNulls(segmentNames, "segment names");
293                }
294                segments.add(new BasicPathSegment(segmentName));
295            }
296            if (segments.size() == 1) {
297                // Special case of a single-segment name ...
298                return new ChildPath(RootPath.INSTANCE, segments.get(0));
299            }
300            return new BasicPath(segments, true);
301        }
302    
303        /**
304         * {@inheritDoc}
305         */
306        public Path createAbsolutePath( Segment... segments ) {
307            if (segments == null || segments.length == 0) return RootPath.INSTANCE;
308            List<Segment> segmentsList = new ArrayList<Segment>(segments.length);
309            for (Segment segment : segments) {
310                if (segment == null) {
311                    CheckArg.containsNoNulls(segments, "segments");
312                }
313                segmentsList.add(segment);
314            }
315            if (segmentsList.size() == 1) {
316                // Special case of a single-segment name ...
317                return new ChildPath(RootPath.INSTANCE, segmentsList.get(0));
318            }
319            return new BasicPath(segmentsList, true);
320        }
321    
322        /**
323         * {@inheritDoc}
324         * 
325         * @see org.jboss.dna.graph.property.PathFactory#createAbsolutePath(java.lang.Iterable)
326         */
327        public Path createAbsolutePath( Iterable<Segment> segments ) {
328            List<Segment> segmentsList = new LinkedList<Segment>();
329            for (Segment segment : segments) {
330                if (segment == null) {
331                    CheckArg.containsNoNulls(segments, "segments");
332                }
333                segmentsList.add(segment);
334            }
335            if (segmentsList.isEmpty()) return RootPath.INSTANCE;
336            if (segmentsList.size() == 1) {
337                // Special case of a single-segment name ...
338                return new ChildPath(RootPath.INSTANCE, segmentsList.get(0));
339            }
340            return new BasicPath(segmentsList, true);
341        }
342    
343        /**
344         * <p>
345         * {@inheritDoc}
346         * </p>
347         * 
348         * @see org.jboss.dna.graph.property.PathFactory#createRelativePath()
349         */
350        public Path createRelativePath() {
351            return BasicPath.EMPTY_RELATIVE;
352        }
353    
354        /**
355         * {@inheritDoc}
356         */
357        public Path createRelativePath( Name... segmentNames ) {
358            if (segmentNames == null || segmentNames.length == 0) return BasicPath.EMPTY_RELATIVE;
359            List<Segment> segments = new ArrayList<Segment>(segmentNames.length);
360            for (Name segmentName : segmentNames) {
361                if (segmentName == null) {
362                    CheckArg.containsNoNulls(segmentNames, "segment names");
363                }
364                segments.add(new BasicPathSegment(segmentName));
365            }
366            return new BasicPath(segments, false);
367        }
368    
369        /**
370         * {@inheritDoc}
371         */
372        public Path createRelativePath( Segment... segments ) {
373            if (segments == null || segments.length == 0) return BasicPath.EMPTY_RELATIVE;
374            List<Segment> segmentsList = new ArrayList<Segment>(segments.length);
375            for (Segment segment : segments) {
376                if (segment == null) {
377                    CheckArg.containsNoNulls(segments, "segments");
378                }
379                segmentsList.add(segment);
380            }
381            return new BasicPath(segmentsList, false);
382        }
383    
384        /**
385         * {@inheritDoc}
386         * 
387         * @see org.jboss.dna.graph.property.PathFactory#createRelativePath(java.lang.Iterable)
388         */
389        public Path createRelativePath( Iterable<Segment> segments ) {
390            List<Segment> segmentsList = new LinkedList<Segment>();
391            for (Segment segment : segments) {
392                if (segment == null) {
393                    CheckArg.containsNoNulls(segments, "segments");
394                }
395                segmentsList.add(segment);
396            }
397            if (segmentsList.isEmpty()) return BasicPath.EMPTY_RELATIVE;
398            return new BasicPath(segmentsList, false);
399        }
400    
401        /**
402         * {@inheritDoc}
403         * 
404         * @see org.jboss.dna.graph.property.PathFactory#create(org.jboss.dna.graph.property.Path, org.jboss.dna.graph.property.Path)
405         */
406        public Path create( Path parentPath,
407                            Path childPath ) {
408            CheckArg.isNotNull(parentPath, "parent path");
409            CheckArg.isNotNull(childPath, "child path");
410            if (childPath.size() == 0) return parentPath;
411            if (parentPath.size() == 0) {
412                // Just need to return the child path, but it must be absolute if the parent is ...
413                if (childPath.isAbsolute() == parentPath.isAbsolute()) return childPath;
414                // They aren't the same absoluteness, so create a new one ...
415                return new BasicPath(childPath.getSegmentsList(), parentPath.isAbsolute());
416            }
417            List<Segment> segments = new ArrayList<Segment>(parentPath.size() + childPath.size());
418            for (Segment seg : parentPath) {
419                segments.add(seg);
420            }
421            for (Segment seg : childPath) {
422                segments.add(seg);
423            }
424            return new BasicPath(segments, parentPath.isAbsolute());
425        }
426    
427        /**
428         * {@inheritDoc}
429         */
430        public Path create( Path parentPath,
431                            Name segmentName,
432                            int index ) {
433            CheckArg.isNotNull(parentPath, "parent path");
434            CheckArg.isNotNull(segmentName, "segment name");
435            return new ChildPath(parentPath, new BasicPathSegment(segmentName, index));
436        }
437    
438        /**
439         * {@inheritDoc}
440         * 
441         * @see org.jboss.dna.graph.property.PathFactory#create(org.jboss.dna.graph.property.Path, java.lang.String, int)
442         */
443        public Path create( Path parentPath,
444                            String segmentName,
445                            int index ) {
446            return create(parentPath, nameValueFactory.create(segmentName), index);
447        }
448    
449        /**
450         * {@inheritDoc}
451         */
452        public Path create( Path parentPath,
453                            Name... segmentNames ) {
454            CheckArg.isNotNull(parentPath, "parent path");
455            if (segmentNames == null || segmentNames.length == 0) return parentPath;
456            if (segmentNames.length == 1 && segmentNames[0] != null) {
457                return new ChildPath(parentPath, new BasicPathSegment(segmentNames[0]));
458            }
459    
460            List<Segment> segments = new ArrayList<Segment>(parentPath.size() + 1);
461            segments.addAll(parentPath.getSegmentsList());
462            for (Name segmentName : segmentNames) {
463                if (segmentName == null) {
464                    CheckArg.containsNoNulls(segmentNames, "segment names");
465                }
466                segments.add(new BasicPathSegment(segmentName));
467            }
468            return new BasicPath(segments, parentPath.isAbsolute());
469        }
470    
471        /**
472         * {@inheritDoc}
473         */
474        public Path create( Path parentPath,
475                            Segment... segments ) {
476            CheckArg.isNotNull(parentPath, "parent path");
477            if (segments == null || segments.length == 0) return RootPath.INSTANCE;
478            if (segments.length == 1 && segments[0] != null) {
479                return new ChildPath(parentPath, segments[0]);
480            }
481    
482            List<Segment> segmentsList = new ArrayList<Segment>(parentPath.size() + 1);
483            segmentsList.addAll(parentPath.getSegmentsList());
484            for (Segment segment : segments) {
485                if (segment == null) {
486                    CheckArg.containsNoNulls(segments, "segments");
487                }
488                segmentsList.add(segment);
489            }
490            return new BasicPath(segmentsList, parentPath.isAbsolute());
491        }
492    
493        /**
494         * {@inheritDoc}
495         * 
496         * @see org.jboss.dna.graph.property.PathFactory#create(org.jboss.dna.graph.property.Path, java.lang.Iterable)
497         */
498        public Path create( Path parentPath,
499                            Iterable<Segment> segments ) {
500            CheckArg.isNotNull(parentPath, "parent path");
501    
502            List<Segment> segmentsList = new LinkedList<Segment>();
503            segmentsList.addAll(parentPath.getSegmentsList());
504            for (Segment segment : segments) {
505                if (segment == null) {
506                    CheckArg.containsNoNulls(segments, "segments");
507                }
508                segmentsList.add(segment);
509            }
510            if (segmentsList.isEmpty()) return RootPath.INSTANCE;
511            if (segmentsList.size() == 0) return new ChildPath(parentPath, segmentsList.get(0));
512            return new BasicPath(segmentsList, parentPath.isAbsolute());
513        }
514    
515        /**
516         * {@inheritDoc}
517         * 
518         * @see org.jboss.dna.graph.property.PathFactory#create(org.jboss.dna.graph.property.Path, java.lang.String)
519         */
520        public Path create( Path parentPath,
521                            String subpath ) {
522            CheckArg.isNotNull(parentPath, "parentPath");
523            CheckArg.isNotNull(subpath, "subpath");
524            subpath = subpath.trim();
525            boolean singleChild = subpath.indexOf(Path.DELIMITER) == -1;
526            if (!singleChild && subpath.startsWith("./")) {
527                if (subpath.length() == 2) return parentPath; // self reference
528                // Remove the leading parent reference and try again to see if single child ...
529                subpath = subpath.substring(2);
530                singleChild = subpath.indexOf(Path.DELIMITER) == -1;
531            }
532            if (singleChild) {
533                try {
534                    Path.Segment childSegment = createSegment(subpath);
535                    return new ChildPath(parentPath, childSegment);
536                } catch (IllegalArgumentException t) {
537                    // Catch and eat, letting the slower implementation catch anything ...
538                }
539            }
540            // It is a subpath with more than one segment, so create a relative path for the subpath ...
541            Path relativeSubpath = create(subpath);
542            return create(parentPath, relativeSubpath);
543    
544        }
545    
546        /**
547         * {@inheritDoc}
548         */
549        public Segment createSegment( Name segmentName ) {
550            CheckArg.isNotNull(segmentName, "segment name");
551            if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
552            if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
553            return new BasicPathSegment(segmentName);
554        }
555    
556        /**
557         * {@inheritDoc}
558         */
559        public Segment createSegment( Name segmentName,
560                                      int index ) {
561            CheckArg.isNotNull(segmentName, "segment name");
562            if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
563            if (Path.PARENT_NAME.equals(segmentName)) return Path.PARENT_SEGMENT;
564            return new BasicPathSegment(segmentName, index);
565        }
566    
567        /**
568         * {@inheritDoc}
569         * 
570         * @see org.jboss.dna.graph.property.PathFactory#createSegment(java.lang.String)
571         */
572        public Segment createSegment( String segmentName ) {
573            return createSegment(segmentName, getDecoder());
574        }
575    
576        /**
577         * <p>
578         * {@inheritDoc}
579         * </p>
580         * 
581         * @see org.jboss.dna.graph.property.PathFactory#createSegment(java.lang.String, org.jboss.dna.common.text.TextDecoder)
582         */
583        public Segment createSegment( String segmentName,
584                                      TextDecoder decoder ) {
585            CheckArg.isNotNull(segmentName, "segment name");
586            if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
587            if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
588            int startBracketNdx = segmentName.indexOf('[');
589            if (startBracketNdx < 0) {
590                return new BasicPathSegment(this.nameValueFactory.create(segmentName, decoder));
591            }
592            int endBracketNdx = segmentName.indexOf(']', startBracketNdx);
593            if (endBracketNdx < 0) {
594                throw new IllegalArgumentException(GraphI18n.missingEndBracketInSegmentName.text(segmentName));
595            }
596            String ndx = segmentName.substring(startBracketNdx + 1, endBracketNdx);
597            try {
598                return new BasicPathSegment(this.nameValueFactory.create(segmentName.substring(0, startBracketNdx), decoder),
599                                            Integer.parseInt(ndx));
600            } catch (NumberFormatException err) {
601                throw new ValueFormatException(segmentName, getPropertyType(), GraphI18n.invalidIndexInSegmentName.text(ndx,
602                                                                                                                        segmentName));
603            }
604        }
605    
606        /**
607         * {@inheritDoc}
608         */
609        public Segment createSegment( String segmentName,
610                                      int index ) {
611            CheckArg.isNotNull(segmentName, "segment name");
612            if (Path.SELF.equals(segmentName)) return Path.SELF_SEGMENT;
613            if (Path.PARENT.equals(segmentName)) return Path.PARENT_SEGMENT;
614            return new BasicPathSegment(this.nameValueFactory.create(segmentName), index);
615        }
616    
617        /**
618         * {@inheritDoc}
619         */
620        public Path create( Reference value ) {
621            throw new ValueFormatException(value, getPropertyType(),
622                                           GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
623                                                                              Reference.class.getSimpleName(),
624                                                                              value));
625        }
626    
627        /**
628         * {@inheritDoc}
629         */
630        public Path create( URI value ) {
631            if (value == null) return null;
632            String asciiString = value.toASCIIString();
633            // Remove any leading "./" ...
634            if (asciiString.startsWith("./") && asciiString.length() > 2) {
635                asciiString = asciiString.substring(2);
636            }
637            if (asciiString.indexOf('/') == -1) {
638                return create(asciiString);
639            }
640            throw new ValueFormatException(value, getPropertyType(), GraphI18n.errorConvertingType.text(URI.class.getSimpleName(),
641                                                                                                        Path.class.getSimpleName(),
642                                                                                                        value));
643        }
644    
645        /**
646         * {@inheritDoc}
647         * 
648         * @see org.jboss.dna.graph.property.ValueFactory#create(java.util.UUID)
649         */
650        public Path create( UUID value ) {
651            throw new ValueFormatException(value, getPropertyType(), GraphI18n.unableToCreateValue.text(getPropertyType().getName(),
652                                                                                                        UUID.class.getSimpleName(),
653                                                                                                        value));
654        }
655    
656        /**
657         * {@inheritDoc}
658         */
659        public Path create( byte[] value ) {
660            // First attempt to create a string from the value, then a long from the string ...
661            return create(getStringValueFactory().create(value));
662        }
663    
664        /**
665         * {@inheritDoc}
666         * 
667         * @see org.jboss.dna.graph.property.ValueFactory#create(org.jboss.dna.graph.property.Binary)
668         */
669        public Path create( Binary value ) throws ValueFormatException, IoException {
670            // First create a string and then create the boolean from the string value ...
671            return create(getStringValueFactory().create(value));
672        }
673    
674        /**
675         * {@inheritDoc}
676         */
677        public Path create( InputStream stream,
678                            long approximateLength ) throws IoException {
679            // First attempt to create a string from the value, then a double from the string ...
680            return create(getStringValueFactory().create(stream, approximateLength));
681        }
682    
683        /**
684         * {@inheritDoc}
685         */
686        public Path create( Reader reader,
687                            long approximateLength ) throws IoException {
688            // First attempt to create a string from the value, then a double from the string ...
689            return create(getStringValueFactory().create(reader, approximateLength));
690        }
691    
692        /**
693         * {@inheritDoc}
694         */
695        @Override
696        protected Path[] createEmptyArray( int length ) {
697            return new Path[length];
698        }
699    
700    }