Example #1
0
func main() {
	argo.LoadLookupCache(LookupCacheFile)
	defer argo.SaveLookupCache(LookupCacheFile)

	startTime := time.Now()

	args := &Args{
		OutFile: "-",
	}

	p := argparse.New("A tool for manipulating RDF files.")
	p.Option('o', "output", "OutFile", 1, argparse.Store, "FILENAME", "The file to write output to. Default: standard output.")
	p.Option('u', "url", "URLs", 1, argparse.Append, "URL", "A URL to download from and add to the graph. Can be used multiple times. Default: no URLs will be downloaded.")
	p.Option('I', "input-format", "InputFormat", 1, argparse.Choice(argparse.Store, Parsers...), "FORMAT", "The format to parse all input sources as. Default: determine by the file extension, or fall back to rdfxml if unavailable.")
	p.Option('i', "stdin-format", "StdinFormat", 1, argparse.Choice(argparse.Store, Parsers...), "FORMAT", "The format to parse stdin as. The formats for all other sources (files and URLs) are still determined by their file extensions. Default: rdfxml.")
	p.Option('O', "output-format", "OutputFormat", 1, argparse.Choice(argparse.Store, Serializers...), "FORMAT", "The format to write output to. Default: determine by the file extension, or fall back to rdfxml if unavailable.")
	p.Option('F', "formats", "ShowFormats", 0, argparse.StoreConst(true), "", "Display a list of formats.")
	p.Option('r', "rewrite", "Rewrites", 2, argparse.Append, "FIND REPLACE", "Replaces all URIs and blank nodes that match the standard regular expression FIND with the URI REPLACE. Within REPLACE, patterns such as $1, $2 etc. expanding to the text of the first and second submatch respectively. This option can be used multiple times. Input and output strings that have the prefix '_:' are interpreted as blank nodes; otherwise they are URIs.")
	p.Option(0, "rewrite-subject", "SubjectRewrites", 2, argparse.Append, "FIND REPLACE", "Like -r/--rewrite, but only applies to subject terms.")
	p.Option(0, "rewrite-predicate", "PredicateRewrites", 2, argparse.Append, "FIND REPLACE", "Like -r/--rewrite, but only applies to predicate terms.")
	p.Option(0, "rewrite-object", "ObjectRewrites", 2, argparse.Append, "FIND REPLACE", "Like -r/--rewrite, but only applies to object terms.")
	p.Argument("Files", argparse.ZeroOrMore, argparse.Store, "filename", "Files to parse and add to the graph.")
	err := p.Parse(args)

	if err != nil {
		ansi.Fprintf(os.Stderr, ansi.RedBold, "Error when parsing arguments: %s\n", err.Error())
		os.Exit(1)
	}

	if args.ShowFormats {
		fmt.Printf("Input formats:\n")

		for _, id := range Parsers {
			fmt.Printf("  %s - %s\n", id, argo.Formats[id].Name)
		}

		fmt.Printf("\nOutput formats:\n")

		for _, id := range Serializers {
			fmt.Printf("  %s - %s\n", id, argo.Formats[id].Name)
		}

		return
	}

	// =============================================================================================

	var rewrites, subjectRewrites, predicateRewrites, objectRewrites []Rewrite

	if args.Rewrites != nil {
		rewrites = make([]Rewrite, len(args.Rewrites)/2)

		for i := 0; i < len(args.Rewrites); i += 2 {
			rewrites[i/2].Regexp = regexp.MustCompile(args.Rewrites[i])
			rewrites[i/2].Template = args.Rewrites[i+1]
		}
	}

	if args.SubjectRewrites != nil {
		subjectRewrites = make([]Rewrite, len(args.SubjectRewrites)/2)

		for i := 0; i < len(args.SubjectRewrites); i += 2 {
			subjectRewrites[i/2].Regexp = regexp.MustCompile(args.SubjectRewrites[i])
			subjectRewrites[i/2].Template = args.SubjectRewrites[i+1]
		}
	}

	if args.PredicateRewrites != nil {
		predicateRewrites = make([]Rewrite, len(args.PredicateRewrites)/2)

		for i := 0; i < len(args.PredicateRewrites); i += 2 {
			predicateRewrites[i/2].Regexp = regexp.MustCompile(args.PredicateRewrites[i])
			predicateRewrites[i/2].Template = args.PredicateRewrites[i+1]
		}
	}

	if args.ObjectRewrites != nil {
		objectRewrites = make([]Rewrite, len(args.ObjectRewrites)/2)

		for i := 0; i < len(args.ObjectRewrites); i += 2 {
			objectRewrites[i/2].Regexp = regexp.MustCompile(args.ObjectRewrites[i])
			objectRewrites[i/2].Template = args.ObjectRewrites[i+1]
		}
	}

	parseChan := make(chan *argo.Triple)
	serializeChan := make(chan *argo.Triple)
	parseErrChan := make(chan error)
	serializeErrChan := make(chan error)
	prefixMap := make(map[string]string)

	var output io.Writer
	format := argo.Formats["rdfxml"]

	if args.OutFile == "-" {
		output = os.Stdout

	} else {
		output, err = os.Create(args.OutFile)
		if err != nil {
			msg(ansi.RedBold, "Error when opening '%s' for writing: %s\n", args.OutFile, err.Error())
			os.Exit(1)
		}

		format = argo.FormatFromFilename(args.OutFile)
	}

	if args.OutputFormat != "" {
		format = argo.Formats[args.OutputFormat]
	}

	msg(ansi.White, "Serializing as %s...\n", format.Name)
	go read(parseChan, parseErrChan, prefixMap, args)
	go format.Serializer(output, serializeChan, serializeErrChan, prefixMap)

	go func() {
		for triple := range parseChan {
			rewrite(&triple.Subject, rewrites, subjectRewrites)
			rewrite(&triple.Predicate, rewrites, predicateRewrites)
			rewrite(&triple.Object, rewrites, objectRewrites)

			serializeChan <- triple
			TriplesProcessed++
		}

		close(serializeChan)
	}()

	for err = range parseErrChan {
		msg(ansi.RedBold, "Error: %s\n", err.Error())
	}

	for err = range serializeErrChan {
		msg(ansi.RedBold, "Error: %s\n", err.Error())
	}

	ms := float64(time.Since(startTime).Nanoseconds()) / 1000000.0
	msg(ansi.White, "\n%d triples processed in %.3f seconds (%.3f ms)\n", TriplesProcessed, ms/1000.0, ms)
	msg(ansi.White, "%d terms rewritten\n", Rewritten)
}
Example #2
0
func main() {
	p := argparse.New("A SPARQL query & update client")
	p.Argument("Endpoint", 1, argparse.Store, "endpoint_uri", "The SPARQL endpoint URI. It is used for all query operations, and update operations when -u is not specified.")
	p.Option('u', "update-endpoint", "UpdateEndpoint", 1, argparse.Store, "URI", "An alternative endpoint URI that is only used for SPARQL update operations. Default: use the query endpoint URI.")
	p.Option('f', "fuseki", "UseFuseki", 0, argparse.StoreConst(true), "", "Interpret endpoint_uri as the URI of a Fuseki dataset, and then use its query and update services as the corresponding endpoints for the session.")
	p.Option('d', "debug", "Debug", 0, argparse.StoreConst(true), "", "Show debug info.")

	args := &Args{}
	err := p.Parse(args)

	if err != nil {
		if cmdLineErr, ok := err.(argparse.CommandLineError); ok {
			ansi.Fprintln(os.Stderr, ansi.RedBold, string(cmdLineErr))
			p.Help()
			os.Exit(2)

		} else {
			die(err, true)
		}
	}

	var queryService, updateService sparql.SparqlService

	if args.UseFuseki {
		dataset := fuseki.NewDataset(args.Endpoint)
		queryService = dataset.QueryService()
		updateService = dataset.UpdateService()

	} else {
		queryService = sparql.NewSparqlService(args.Endpoint)

		if args.UpdateEndpoint != "" {
			updateService = sparql.NewSparqlService(args.UpdateEndpoint)

		} else {
			updateService = queryService
		}
	}

	queryService.Debug = args.Debug
	updateService.Debug = args.Debug

	stdinReader := bufio.NewReader(os.Stdin)
	prefixes := make(map[string]string) // Prefix -> Base URI
	format := argo.Formats["rdfxml"]

mainloop:
	for {
		fmt.Print("> ")

		line, err := stdinReader.ReadString('\n')
		if err == io.EOF {
			return
		}

		if die(err, false) {
			continue mainloop
		}

		line = trimPrefixes(line[:len(line)-1], prefixes)
		line = strings.Trim(line, " \r\n\t")

		if line == "" {
			continue mainloop
		}

		verb := line
		spacePos := strings.IndexRune(line, ' ')
		if spacePos >= 0 {
			verb = line[:spacePos]
		}

		switch strings.ToUpper(verb) {
		case "SELECT":
			rp, err := queryService.Select(line)
			if die(err, false) {
				continue mainloop
			}

			vars := rp.Vars()

			var table Table
			table.SetHeader(vars...)

			for result := range rp.ResultChan() {
				fields := make([]string, len(vars))

				for i, v := range vars {
					fields[i] = result[v].String()
				}

				table.AddRow(fields...)
			}

			ansi.AttrOn(ansi.Yellow)
			table.Print()
			ansi.AttrOff(ansi.Yellow)

		case "ASK":
			result, err := queryService.Ask(line)
			if die(err, false) {
				continue mainloop
			}

			ansi.Printf(ansi.Magenta, "Result: %t\n", result)

		case "CONSTRUCT", "DESCRIBE":
			graph, err := queryService.Graph(line)
			if die(err, false) {
				continue mainloop
			}

			updateRev(graph.Prefixes, prefixes)

			ansi.AttrOn(ansi.Cyan)
			graph.Serialize(format.Serializer, os.Stdout)
			ansi.AttrOff(ansi.Cyan)

		case "INSERT", "DELETE", "LOAD", "CLEAR", "CREATE", "DROP", "COPY", "MOVE", "ADD":
			err := updateService.Update(line)
			if die(err, false) {
				continue mainloop
			}

			ansi.Println(ansi.GreenBold, "OK")

		case "FORMAT":
			formatName := strings.ToLower(line[spacePos+1:])
			newFormat, ok := argo.Formats[formatName]
			if !ok {
				ansi.Fprintf(os.Stderr, ansi.RedBold, "Invalid format: %s\n", formatName)
			}

			format = newFormat

		default:
			ansi.Fprintf(os.Stderr, ansi.RedBold, "Invalid command: %s\n", verb)
		}
	}
}
Example #3
0
func main() {
	p := argparse.New("")

	p.Argument("Pattern", 1, argparse.Store, "PATTERN", "The pattern specifying which filenames should be matched. It is similar to a shell pattern: '*' matches any string of digits, '?' matches exactly one digit and any other character matches itself.")
	p.Argument("Dir", 1, argparse.Store, "DIRECTORY", "The directory to search in.")

	p.Option('l', "list", "Action", 0, argparse.StoreConst(List), "", "List all files in the directory that match this pattern, sorted in numerical order.")
	p.Option('n', "next", "Action", 0, argparse.StoreConst(Next), "", "Return the next logical filename in the directory (i.e. a filename that fits the pattern, with the first group set to the maximum value found in the directory, plus one.)")
	p.Option('0', "zeros", "Zeros", 0, argparse.StoreConst(true), "", "Separate files produced by -l/--list with nulls (0-bytes) instead of newlines (for sending output to xargs -0 etc.)")

	args := &Args{}
	err := p.Parse(args)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
		os.Exit(1)
	}

	switch args.Action {
	case NoAction:
		p.Usage()
		fmt.Fprintf(os.Stderr, "No action was given (try one of -l, -n)\n")
		os.Exit(2)

	case List:
		pattern := ParsePattern(args.Pattern)
		files := make([]File, 0)

		for filename := range ListDir(args.Dir) {
			match := pattern.Match(filename)
			if match != nil {
				files = append(files, File{filename, match})
			}
		}

		f := Files{files, pattern.NumGroups()}
		sort.Sort(f)

		for _, file := range f.Files {
			if args.Zeros {
				fmt.Print(file.Name + "\x00")
			} else {
				fmt.Println(file.Name)
			}
		}

	case Next:
		n := 0
		pattern := ParsePattern(args.Pattern)
		if pattern.NumGroups() < 1 {
			p.Usage()
			fmt.Fprintf(os.Stderr, "At least 1 group must be specified\n")
			os.Exit(2)
		}

		for filename := range ListDir(args.Dir) {
			match := pattern.Match(filename)
			if match != nil && match[0] > n {
				n = match[0]
			}
		}

		groups := make([]int, pattern.NumGroups())
		groups[0] = n + 1

		fmt.Println(pattern.Make(groups))
	}
}