| // Copyright 2017 Google Inc. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // Package results contains the result type returned by the classifier backend. |
| // Placing the type into a separate module allows us to swap out backends and |
| // still use the same datatype. |
| package results |
| |
| import ( |
| "bufio" |
| "fmt" |
| "os" |
| "sort" |
| ) |
| |
| // LicenseType is the assumed type of the unknown license. |
| type LicenseType struct { |
| Filename string |
| Name string |
| MatchType string |
| Variant string |
| Confidence float64 |
| StartLine int |
| EndLine int |
| } |
| |
| // LicenseTypes is a list of LicenseType objects. |
| type LicenseTypes []*LicenseType |
| |
| func (lt LicenseTypes) Len() int { return len(lt) } |
| func (lt LicenseTypes) Swap(i, j int) { lt[i], lt[j] = lt[j], lt[i] } |
| func (lt LicenseTypes) Less(i, j int) bool { |
| if lt[i].Confidence > lt[j].Confidence { |
| return true |
| } |
| if lt[i].Confidence < lt[j].Confidence { |
| return false |
| } |
| if lt[i].Filename < lt[j].Filename { |
| return true |
| } |
| if lt[i].Filename > lt[j].Filename { |
| return false |
| } |
| return lt[i].EndLine < lt[j].EndLine |
| } |
| |
| // Classification is the license classification for a segment of a file. |
| type Classification struct { |
| Name string |
| Confidence float64 |
| StartLine int |
| EndLine int |
| Text string `json:",omitempty"` |
| } |
| |
| // Classifications contains all license classifications for a file |
| type Classifications []*Classification |
| |
| // FileClassifications contains the license classifications for a particular file. |
| type FileClassifications struct { |
| Filepath string |
| Classifications Classifications |
| } |
| |
| //JSONResult is the format for the jr JSON file |
| type JSONResult []*FileClassifications |
| |
| func (jr JSONResult) Len() int { return len(jr) } |
| func (jr JSONResult) Swap(i, j int) { jr[i], jr[j] = jr[j], jr[i] } |
| func (jr JSONResult) Less(i, j int) bool { return jr[i].Filepath < jr[j].Filepath } |
| |
| // readFileLines will read a specified range of lines of a file |
| func readFileLines(filename string, startLine, endLine int) (string, error) { |
| f, err := os.Open(filename) |
| if err != nil { |
| return "", err |
| } |
| defer f.Close() |
| |
| scanner := bufio.NewScanner(f) |
| lines := "" |
| i := 0 |
| for scanner.Scan() { |
| i++ // lines are 1-indexed |
| if i < startLine { |
| continue |
| } else if i > endLine { |
| break |
| } |
| lines += scanner.Text() + "\n" |
| } |
| if i < endLine { |
| return "", fmt.Errorf( |
| "line %d was the last line read from file %s, but endLine was set to %d", i, filename, endLine) |
| } |
| return lines, nil |
| } |
| |
| // NewJSONResult creates a new JSONResult object from a LicenseTypes object. |
| func NewJSONResult(licenses LicenseTypes, includeText bool) (JSONResult, error) { |
| fMap := map[string]*FileClassifications{} |
| for _, l := range licenses { |
| currF, ok := fMap[l.Filename] |
| if !ok { |
| currF = &FileClassifications{Filepath: l.Filename} |
| fMap[l.Filename] = currF |
| } |
| c := &Classification{ |
| Name: l.Name, |
| Confidence: l.Confidence, |
| StartLine: l.StartLine, |
| EndLine: l.EndLine, |
| } |
| if includeText { |
| text, err := readFileLines(l.Filename, l.StartLine, l.EndLine) |
| if err != nil { |
| return nil, err |
| } |
| c.Text = text |
| } |
| currF.Classifications = append(currF.Classifications, c) |
| } |
| |
| jr := JSONResult{} |
| for _, fc := range fMap { |
| jr = append(jr, fc) |
| } |
| sort.Sort(jr) |
| return jr, nil |
| } |