internal static void SetupLanguage(this Context context, JObject localContext)
 {
     if (localContext.IsPropertySet(JsonLdProcessor.Language))
     {
         if (localContext.Property(JsonLdProcessor.Language).ValueEquals(null))
         {
             context.Language = null;
         }
         else if (!localContext.Property(JsonLdProcessor.Language).ValueIs<string>())
         {
             throw new InvalidOperationException("Invalid default language.");
         }
         else
         {
             context.Language = localContext.Property(JsonLdProcessor.Language).ValueAs<string>().ToLower();
         }
     }
 }
 internal static void SetupVocab(this Context context, JObject localContext)
 {
     if (localContext.IsPropertySet(JsonLdProcessor.Vocab))
     {
         string value = localContext.Property(JsonLdProcessor.Vocab).ValueAs<string>();
         if (value == null)
         {
             context.Vocabulary = null;
         }
         else if ((Regex.IsMatch(value, "[a-zA-Z0-9_]+://")) || (value.StartsWith("_:")))
         {
             context.Vocabulary = value;
         }
         else
         {
             throw new InvalidOperationException("Invalid vocab mapping.");
         }
     }
 }
 internal static void SetupBase(this Context context, JObject localContext, IList<string> remoteContexts)
 {
     if ((localContext.IsPropertySet(JsonLdProcessor.Base)) && (remoteContexts.Count == 0))
     {
         string value = localContext.Property(JsonLdProcessor.Base).ValueAs<string>();
         if (value == null)
         {
             context.BaseIri = null;
         }
         else if (Regex.IsMatch(value, "[a-zA-Z0-9_]+://.+"))
         {
             context.BaseIri = value;
         }
         else if ((!Regex.IsMatch(value, "[a-zA-Z0-9_]+:.+")) && (context.BaseIri != null))
         {
             context.BaseIri = JsonLdProcessor.MakeAbsoluteUri(context.BaseIri, value);
         }
         else
         {
             throw new InvalidOperationException("Invalid base IRI.");
         }
     }
 }
        private string ExpandIri(object value, Context context, JObject localContext = null, bool documentRelative = false, bool vocab = false, IDictionary<string, bool> defined = null)
        {
            if (value == null)
            {
                return null;
            }

            string valueString = (value as string);
            if (valueString == null)
            {
                throw new InvalidOperationException(System.String.Format("Cannot expand iri of type '{0}'.", value.GetType()));
            }

            if (IsKeyWord(valueString))
            {
                return valueString;
            }

            if ((localContext != null) && (localContext.IsPropertySet(valueString)) && (!defined.ContainsKey(valueString)))
            {
                CreateTermDefinition(valueString, context, localContext, defined);
            }

            if ((vocab) && (context.ContainsKey(valueString)))
            {
                return (context[valueString] != null ? context[valueString].Iri : null);
            }

            if (Regex.IsMatch(valueString, "[a-zA-Z0-9_]+:.+"))
            {
                string prefix = valueString.Substring(0, valueString.IndexOf(':'));
                string suffix = valueString.Substring(prefix.Length + 1);
                if ((prefix == "_") || (suffix.StartsWith("//")))
                {
                    return valueString;
                }

                if ((localContext != null) && (!defined.ContainsKey(prefix)))
                {
                    CreateTermDefinition(prefix, context, localContext, defined);
                }

                if (context.ContainsKey(prefix))
                {
                    return context[prefix].Iri.ToString() + suffix;
                }

                return valueString;
            }

            if ((vocab) && (context.Vocabulary != null))
            {
                return MakeAbsoluteUri(context.Vocabulary, valueString);
            }

            if (documentRelative)
            {
                return MakeAbsoluteUri(context.BaseIri, valueString);
            }

            return valueString;
        }
        private bool ExpandKeyword(JObject result, JProperty _property, string activeProperty, string expandedProperty, Context activeContext, IList<string> remoteContexts, out JToken expandedValue)
        {
            bool @continue = false;
            expandedValue = null;
            string key = _property.Name;
            JToken value = _property.Value;
            if (activeProperty == Reverse)
            {
                throw new InvalidOperationException("Invalid reverse property map.");
            }

            if (result.IsPropertySet(expandedProperty))
            {
                throw new InvalidOperationException("Colliding keywords.");
            }

            switch (expandedProperty)
            {
                case Id:
                case Type:
                case Value:
                case Language:
                case Index:
                case List:
                    System.Reflection.MethodInfo expandMethodInfo = GetType().GetMethod("Expand" + Char.ToUpper(expandedProperty[1]) + expandedProperty.Substring(2), System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
                    object[] arguments = { result, _property, activeProperty, expandedProperty, activeContext, remoteContexts, expandedValue };
                    @continue = (bool)expandMethodInfo.Invoke(this, arguments);
                    expandedValue = (JToken)arguments[arguments.Length - 1];
                    if (@continue)
                    {
                        return @continue;
                    }

                    break;
                case Graph:
                case Set:
                    expandedValue = Expand((expandedProperty == Graph ? Graph : activeProperty), value, activeContext, remoteContexts);
                    break;
                case Reverse:
                    @continue = ExpandReverse(result, _property, activeProperty, expandedProperty, activeContext, remoteContexts, out expandedValue);
                    return @continue;
            }

            if (expandedValue != null)
            {
                result[expandedProperty] = expandedValue;
            }

            return @continue = true;
        }
        private JToken Expand(string activeProperty, JObject @object, Context activeContext, IList<string> remoteContexts)
        {
            JObject result = new JObject();
            foreach (JProperty _property in @object.Properties().OrderBy(item => item.Name))
            {
                string key = _property.Name;
                JToken value = _property.Value;
                if (key == Context)
                {
                    activeContext = ProcessContext(activeContext, (JToken)value, remoteContexts);
                    continue;
                }

                string expandedProperty = ExpandIri(key, activeContext, (JObject)null, false, true, null);
                JToken expandedValue = null;
                if ((expandedProperty == null) || ((expandedProperty.IndexOf(':') == -1) && (!IsKeyWord(expandedProperty))))
                {
                    continue;
                }

                if (IsKeyWord(expandedProperty))
                {
                    if (ExpandKeyword(result, _property, activeProperty, expandedProperty, activeContext, remoteContexts, out expandedValue))
                    {
                        continue;
                    }
                }
                else if ((activeContext.ContainsKey(key)) && (activeContext[key].Container == Language) && (value is JObject))
                {
                    expandedValue = ExpandLanguageMap(result, _property, activeProperty, expandedProperty, activeContext, remoteContexts);
                }
                else if ((activeContext.ContainsKey(key)) && (activeContext[key].Container == Index) && (value is JObject))
                {
                    expandedValue = ExpandIndexMap(result, _property, activeProperty, expandedProperty, activeContext, remoteContexts);
                }
                else
                {
                    expandedValue = Expand(key, value, activeContext, remoteContexts);
                }

                if (expandedValue == null)
                {
                    continue;
                }

                if ((activeContext.ContainsKey(key)) && (activeContext[key].Container == List))
                {
                    expandedValue = (expandedValue is JArray ? new JObject(new JProperty(List, expandedValue)) : expandedValue);
                    expandedValue = ((!(expandedValue is JObject)) || (!((JObject)expandedValue).IsPropertySet(List)) ? new JObject(new JProperty(List, new JArray(expandedValue))) : expandedValue);
                }

                if ((activeContext.ContainsKey(key)) && (activeContext[key].IsReverse))
                {
                    JObject reverseMap = (JObject)(!result.IsPropertySet(Reverse) ? result[Reverse] = new JObject() : result[Reverse]);
                    foreach (JToken item in (JArray)(expandedValue = expandedValue.AsArray()))
                    {
                        if ((item is JObject) && ((((JObject)item).IsPropertySet(Value)) || (((JObject)item).IsPropertySet(List))))
                        {
                            throw new InvalidOperationException("Invalid reverse property value.");
                        }

                        ((JArray)(!reverseMap.IsPropertySet(expandedProperty) ? reverseMap[expandedProperty] = new JArray() : reverseMap[expandedProperty])).Merge(item);
                    }
                }
                else
                {
                    ((JArray)(!result.IsPropertySet(expandedProperty) ? result[expandedProperty] = new JArray() : result[expandedProperty])).Merge(expandedValue);
                }
            }

            return ValidateExpandedObject(activeProperty, result);
        }
        private JToken ValidateExpandedObject(string activeProperty, JObject result)
        {
            if (result.IsPropertySet(Value))
            {
                if ((result.Properties().Any(property => (property.Name != Value) && (property.Name != Language) && (property.Name != Type) && (property.Name != Index))) ||
                    ((result.Property(Language) != null) && (result.Property(Type) != null)))
                {
                    throw new InvalidOperationException("Invalid value object.");
                }

                if (result.Property(Value).ValueEquals(null))
                {
                    return result = null;
                }
                else if ((!result.Property(Value).ValueIs<string>()) && (result.IsPropertySet(Language)))
                {
                    throw new InvalidOperationException("Invalid language-tagged value.");
                }
                else if ((result.IsPropertySet(Type)) && (!result.Property(Type).ValueIs<Uri>()))
                {
                    throw new InvalidOperationException("Invalid typed value.");
                }
            }
            else if ((result.IsPropertySet(Type)) && (!(result[Type] is JArray)))
            {
                result[Type] = new JArray(result[Type]);
            }
            else if (result.IsPropertySet(Set))
            {
                if (result[Set] is JArray)
                {
                    return result[Set];
                }
                else
                {
                    result = (JObject)result[Set];
                }
            }

            if ((result.Property(Language) != null) && (result.Properties().Count() == 1))
            {
                result = null;
            }

            return (((activeProperty == null) || (activeProperty == Graph)) && ((result.PropertyCount() == 0) || ((result.IsPropertySet(Value)) || (result.IsPropertySet(List))) || ((result.IsPropertySet(Id)) && (result.PropertyCount() == 1))) ? null : result);
        }
        private void GenerateNodeMap(JObject element, JObject nodeMap, IDictionary<string, string> identifierMap, ref int counter, string activeGraph = Default, JToken activeSubject = null, string activeProperty = null, JObject list = null)
        {
            JObject graph = (JObject)nodeMap[activeGraph];
            if (graph == null)
            {
                nodeMap[activeGraph] = graph = new JObject();
            }

            JObject node = null;
            if (activeSubject != null)
            {
                node = (JObject)graph[activeSubject.ToString()];
            }

            if (element.IsPropertySet(Type))
            {
                foreach (JValue item in (JArray)element[Type].AsArray())
                {
                    if (item.ValueAs<string>().StartsWith("_:"))
                    {
                        item.Value = CreateBlankNodeId(item.ValueAs<string>(), identifierMap, ref counter);
                    }
                }
            }

            if (element.IsPropertySet(Value))
            {
                if (list == null)
                {
                    if (!node.IsPropertySet(activeProperty))
                    {
                        node[activeProperty] = new JArray(element);
                    }
                    else if (!((JArray)node[activeProperty]).Any(item => element.Equals(item)))
                    {
                        ((JArray)node[activeProperty]).Add(element);
                    }
                }
                else
                {
                    ((JArray)list[List]).Add(element);
                }
            }
            else if (element.IsPropertySet(List))
            {
                JObject result = new JObject(new JProperty(List, new JArray()));
                GenerateNodeMap(element[List], nodeMap, identifierMap, ref counter, activeGraph, activeSubject, activeProperty, result);
                ((JArray)node[activeProperty]).Add(result);
            }
            else
            {
                string id;
                if (element.IsPropertySet(Id))
                {
                    id = ((id = element.Property(Id).ValueAs<string>()).StartsWith("_:") ? CreateBlankNodeId(id, identifierMap, ref counter) : id);
                    element.Remove(Id);
                }
                else
                {
                    id = CreateBlankNodeId(null, identifierMap, ref counter);
                }

                if (!graph.IsPropertySet(id))
                {
                    graph[id] = new JObject(new JProperty(Id, id));
                }

                if (activeSubject is JObject)
                {
                    node = (JObject)graph[id];
                    if (!node.IsPropertySet(activeProperty))
                    {
                        node[activeProperty] = new JArray(activeSubject);
                    }
                    else if (!((JArray)node[activeProperty]).Any(item => activeSubject.Equals(item)))
                    {
                        ((JArray)node[activeProperty]).Add(activeSubject);
                    }
                }
                else if (activeProperty != null)
                {
                    JObject reference = new JObject(new JProperty(Id, id));
                    if (list == null)
                    {
                        if (!node.IsPropertySet(activeProperty))
                        {
                            node[activeProperty] = new JArray(reference);
                        }
                        else if (!((JArray)node[activeProperty]).Any(item => reference.Equals(item)))
                        {
                            ((JArray)node[activeProperty]).Add(reference);
                        }
                    }
                    else
                    {
                        ((JArray)list[List]).Add(reference);
                    }
                }

                node = (JObject)graph[id];
                if (element.IsPropertySet(Type))
                {
                    foreach (JValue type in (JArray)element[Type])
                    {
                        if (!(node.IsPropertySet(Type) ? (JArray)node[Type] : node[Type] = new JArray()).Contains(type))
                        {
                            ((JArray)node[Type]).Add(type);
                        }
                    }

                    element.Remove(Type);
                }

                if (element.IsPropertySet(Index))
                {
                    if ((node.IsPropertySet(Index)) && (!node[Index].Equals(element[Index])))
                    {
                        throw new InvalidOperationException("Conflicting indexes.");
                    }

                    node[Index] = element[Index];
                    element.Remove(Index);
                }

                if (element.IsPropertySet(Reverse))
                {
                    JObject referencedNode = new JObject(new JProperty(Id, id));
                    JObject reverseMap = (JObject)element[Reverse];
                    foreach (JProperty _property in reverseMap.Properties())
                    {
                        string property = _property.Name;
                        JArray values = (JArray)_property.Value;
                        foreach (JToken value in values)
                        {
                            GenerateNodeMap(value, nodeMap, identifierMap, ref counter, activeGraph, referencedNode, property);
                        }
                    }

                    element.Remove(Reverse);
                }

                if (element.IsPropertySet(Graph))
                {
                    GenerateNodeMap(element[Graph], nodeMap, identifierMap, ref counter, id);
                    element.Remove(Graph);
                }

                foreach (JProperty _property in element.Properties().OrderBy(property => property.Name))
                {
                    string property = _property.Name;
                    JToken value = _property.Value;
                    if (property.StartsWith("_:"))
                    {
                        property = CreateBlankNodeId(property, identifierMap, ref counter);
                    }

                    if (!node.IsPropertySet(property))
                    {
                        node[property] = new JArray();
                    }

                    GenerateNodeMap(value, nodeMap, identifierMap, ref counter, activeGraph, id, property);
                }
            }
        }