...

Source file src/github.com/xeipuuv/gojsonreference/reference.go

Documentation: github.com/xeipuuv/gojsonreference

     1  // Copyright 2015 xeipuuv ( https://github.com/xeipuuv )
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //   http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // author  			xeipuuv
    16  // author-github 	https://github.com/xeipuuv
    17  // author-mail		xeipuuv@gmail.com
    18  //
    19  // repository-name	gojsonreference
    20  // repository-desc	An implementation of JSON Reference - Go language
    21  //
    22  // description		Main and unique file.
    23  //
    24  // created      	26-02-2013
    25  
    26  package gojsonreference
    27  
    28  import (
    29  	"errors"
    30  	"net/url"
    31  	"path/filepath"
    32  	"runtime"
    33  	"strings"
    34  
    35  	"github.com/xeipuuv/gojsonpointer"
    36  )
    37  
    38  const (
    39  	const_fragment_char = `#`
    40  )
    41  
    42  func NewJsonReference(jsonReferenceString string) (JsonReference, error) {
    43  
    44  	var r JsonReference
    45  	err := r.parse(jsonReferenceString)
    46  	return r, err
    47  
    48  }
    49  
    50  type JsonReference struct {
    51  	referenceUrl     *url.URL
    52  	referencePointer gojsonpointer.JsonPointer
    53  
    54  	HasFullUrl      bool
    55  	HasUrlPathOnly  bool
    56  	HasFragmentOnly bool
    57  	HasFileScheme   bool
    58  	HasFullFilePath bool
    59  }
    60  
    61  func (r *JsonReference) GetUrl() *url.URL {
    62  	return r.referenceUrl
    63  }
    64  
    65  func (r *JsonReference) GetPointer() *gojsonpointer.JsonPointer {
    66  	return &r.referencePointer
    67  }
    68  
    69  func (r *JsonReference) String() string {
    70  
    71  	if r.referenceUrl != nil {
    72  		return r.referenceUrl.String()
    73  	}
    74  
    75  	if r.HasFragmentOnly {
    76  		return const_fragment_char + r.referencePointer.String()
    77  	}
    78  
    79  	return r.referencePointer.String()
    80  }
    81  
    82  func (r *JsonReference) IsCanonical() bool {
    83  	return (r.HasFileScheme && r.HasFullFilePath) || (!r.HasFileScheme && r.HasFullUrl)
    84  }
    85  
    86  // "Constructor", parses the given string JSON reference
    87  func (r *JsonReference) parse(jsonReferenceString string) (err error) {
    88  
    89  	r.referenceUrl, err = url.Parse(jsonReferenceString)
    90  	if err != nil {
    91  		return
    92  	}
    93  	refUrl := r.referenceUrl
    94  
    95  	if refUrl.Scheme != "" && refUrl.Host != "" {
    96  		r.HasFullUrl = true
    97  	} else {
    98  		if refUrl.Path != "" {
    99  			r.HasUrlPathOnly = true
   100  		} else if refUrl.RawQuery == "" && refUrl.Fragment != "" {
   101  			r.HasFragmentOnly = true
   102  		}
   103  	}
   104  
   105  	r.HasFileScheme = refUrl.Scheme == "file"
   106  	if runtime.GOOS == "windows" {
   107  		// on Windows, a file URL may have an extra leading slash, and if it
   108  		// doesn't then its first component will be treated as the host by the
   109  		// Go runtime
   110  		if refUrl.Host == "" && strings.HasPrefix(refUrl.Path, "/") {
   111  			r.HasFullFilePath = filepath.IsAbs(refUrl.Path[1:])
   112  		} else {
   113  			r.HasFullFilePath = filepath.IsAbs(refUrl.Host + refUrl.Path)
   114  		}
   115  	} else {
   116  		r.HasFullFilePath = filepath.IsAbs(refUrl.Path)
   117  	}
   118  
   119  	// invalid json-pointer error means url has no json-pointer fragment. simply ignore error
   120  	r.referencePointer, _ = gojsonpointer.NewJsonPointer(refUrl.Fragment)
   121  
   122  	return
   123  }
   124  
   125  // Creates a new reference from a parent and a child
   126  // If the child cannot inherit from the parent, an error is returned
   127  func (r *JsonReference) Inherits(child JsonReference) (*JsonReference, error) {
   128  	if child.GetUrl() == nil {
   129  		return nil, errors.New("childUrl is nil!")
   130  	}
   131  
   132  	if r.GetUrl() == nil {
   133  		return nil, errors.New("parentUrl is nil!")
   134  	}
   135  
   136  	// Get a copy of the parent url to make sure we do not modify the original.
   137  	// URL reference resolving fails if the fragment of the child is empty, but the parent's is not.
   138  	// The fragment of the child must be used, so the fragment of the parent is manually removed.
   139  	parentUrl := *r.GetUrl()
   140  	parentUrl.Fragment = ""
   141  
   142  	ref, err := NewJsonReference(parentUrl.ResolveReference(child.GetUrl()).String())
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	return &ref, err
   147  }
   148  

View as plain text