int InsertTriFaceCentroidNode(
    int ix0,
    int ix1,
    int ix2,
    NodeVector & vecNodes
) {
    double dX = (vecNodes[ix0].x + vecNodes[ix1].x + vecNodes[ix2].x) / 3.0;
    double dY = (vecNodes[ix0].y + vecNodes[ix1].y + vecNodes[ix2].y) / 3.0;
    double dZ = (vecNodes[ix0].z + vecNodes[ix1].z + vecNodes[ix2].z) / 3.0;

    // Project to sphere
    double dRadius = sqrt(dX*dX + dY*dY + dZ*dZ);

    dX /= dRadius;
    dY /= dRadius;
    dZ /= dRadius;

    // Index
    int ix = vecNodes.size();

    // Insert node
    vecNodes.push_back(Node(dX, dY, dZ));

    return ix;
}
NodeVector SprFrontend::getDeclsFromNode(Node* n, Node*& baseExp) {
    NodeVector res;
    baseExp = nullptr;

    if (!Nest_computeType(n))
        return {};
    n = Nest_explanation(n);
    ASSERT(n);

    // Check if the node is a DeclExp, pointing to the actual references
    if (n->nodeKind == nkSparrowExpDeclExp) {
        baseExp = at(n->referredNodes, 0);
        res = NodeVector(n->referredNodes.beginPtr + 1, n->referredNodes.endPtr);
        return res;
    }

    // Check if this is a ModuleRef; if so, get the it's referred content (inner most package)
    if (n->nodeKind == nkSparrowExpModuleRef) {
        if (Nest_hasProperty(n, propResultingDecl))
            res = {Nest_getCheckPropertyNode(n, propResultingDecl)};
        return res;
    }

    // If the node represents a type, try to get the declaration associated with the type
    Type t = tryGetTypeValue(n);
    if (t && t.hasStorage()) {
        res.push_back(t.referredNode());
    }

    return res;
}
Exemple #3
0
/**
 * Returns the intersection between the TypeSet and the other node. The other
 * node may also be a type set, in which case this function is called
 * recursively to resolve the intersect.
 */
NodePtr intersect(const TypeSet::Ptr& typeSet, const NodePtr& other)
{
	// Intersect all types in the type set with the other type.
	NodeVector newTypes;
	const NodeVector& types = typeSet->getTypes();
	for (NodeVector::const_iterator it = types.begin(); it != types.end(); it++) {
		NodePtr type = intersect(*it, other);
		if (type->isKindOf(kInvalidType)) continue; // skip if the intersect was impossible
		bool exists = false;
		for (NodeVector::iterator is = newTypes.begin(); is != newTypes.end(); is++) {
			if (equal(type, *is)) {
				exists = true;
				break;
			}
		}
		if (!exists) newTypes.push_back(type);
	}

	// Return the new type set if it contains multiple types, a single type if
	// there's only one left after the intersect, or InvalidType if the
	// intersect yielded no types in the set.
	if (newTypes.empty()) {
		return NodePtr(new InvalidType);
	} else if (newTypes.size() == 1) {
		return newTypes.front();
	} else {
		TypeSet::Ptr ts(new TypeSet);
		ts->setTypes(newTypes);
		return ts;
	}
}
void InitRootTypes::wrapFuncArgs(NodeVector& args, const NodeVector& funcArgs)
{
	for (NodeVector::const_iterator it = funcArgs.begin(); it != funcArgs.end(); it++) {
		const FuncArg::Ptr& funcArg = FuncArg::from(*it);
		TupleTypeArg::Ptr arg(new TupleTypeArg);
		arg->setName(funcArg->getName());
		arg->setType(funcArg->getPossibleType());
		args.push_back(arg);
	}
}
Exemple #5
0
NodeVector Node::get_arguments()
{
    NodeVector result;
    for (auto& i : get_inputs())
    {
        {
            result.push_back(i.get_output().get_node());
        }
    }
    return result;
}
Exemple #6
0
NodeVector SprFrontend::getDeclsFromNode(Node* n, Node*& baseExp)
{
    NodeVector res;
    baseExp = nullptr;
    
    n->computeType();
    n = n->explanation();
    ASSERT(n);

    // The node may contain a DeclExp, pointing to the actual references
    Node*const* declExpPtr = n->getPropertyNode(propRefDecls);
    DeclExp* declExp = declExpPtr ? static_cast<DeclExp*>(*declExpPtr) : nullptr;

    if ( declExp )
    {
        baseExp = declExp->baseExp();
        res = declExp->decls();
        return res;
    }
    
    // If the node represents a type, try to get the declaration associated with the type
    Type* t = tryGetTypeValue(n);
    if ( t )
    {
        // If we have a Type as base, try a constructor/concept call
        if ( t->hasStorage() )
        {
            res.push_back(static_cast<StorageType*>(t)->classDecl());
        }
        else if ( t->typeId() == Type::typeConcept )
        {
            res.push_back((Node*) static_cast<ConceptType*>(t)->concept());
        }
        else
            t = nullptr;
    }
    
    return res;
}
Exemple #7
0
// todo: presorted jumplists
NodeVector intersect(NodeVector a, NodeVector b) {
	NodeVector c;
	NodeVector::iterator it;
	for(it = a.begin(); it != a.end(); ++it)
		if (contains(b, *it))
//			c.insert(*it);
			c.push_back(*it);
//	for (int i=0; i < a.size(); i++) {
//		Node* n=a[0];
//		if (contains(b, n)) c.push_back(n);
//	}
    return c;
}
void GenImplicitAccessors::gatherImplAccessors(const NodePtr& node, NodeVector& into)
{
	// Gather getters and setters.
	if (node->isKindOf(kImplAccessor)) {
		into.push_back(node);
	}

	// Gather accessors of the children.
	const NodeVector& children = node->getChildren();
	for (NodeVector::const_iterator it = children.begin(); it != children.end(); it++) {
		gatherImplAccessors(*it, into);
	}
}
Exemple #9
0
NodeVector Node::get_users() const
{
    NodeVector result;

    for (size_t i = 0; i < get_output_size(); ++i)
    {
        for (auto input : get_output_inputs(i))
        {
            result.push_back(input->get_node());
        }
    }

    return result;
}
Exemple #10
0
/**
 * Copies the entries of the input vector of types to the output vector,
 * omitting duplicate types. Useful for TypeSet and UnionType simplification.
 */
void copyUnique(const NodeVector& input, NodeVector& output)
{
	for (NodeVector::const_iterator it = input.begin(); it != input.end(); it++) {
		bool exists = false;
		for (NodeVector::iterator is = output.begin(); is != output.end(); is++) {
			if (equal(*it, *is)) {
				exists = true;
				break;
			}
		}
		if (!exists) output.push_back(*it);
	}
	assert(output.size() <= input.size());
	assert(output.empty() == input.empty());
}
void BronKerbosch::report(const BitSet& R)
{
  NodeVector clique;
  for (size_t i = 0; i < R.size(); ++i)
  {
    if (R[i])
    {
      if (g_verbosity >= VERBOSE_DEBUG)
      {
        std::cerr << " " << _g.id(_bitToNode[i]);
      }
      clique.push_back(_bitToNode[i]);
    }
  }
  _cliques.push_back(clique);
  if (g_verbosity >= VERBOSE_DEBUG)
    std::cerr << std::endl;
}
int InsertSubNode(
    int ix0,
    int ix1,
    double alpha,
    NodeVector & vecNodes
) {
    double dDeltaX = (vecNodes[ix1].x - vecNodes[ix0].x);
    double dDeltaY = (vecNodes[ix1].y - vecNodes[ix0].y);
    double dDeltaZ = (vecNodes[ix1].z - vecNodes[ix0].z);
    double dCartLength =
        sqrt(dDeltaX*dDeltaX + dDeltaY*dDeltaY + dDeltaZ*dDeltaZ);

    double dGamma = acos(0.5 * dCartLength);
    double dTheta = acos(1.0 - 0.5 * dCartLength * dCartLength);
    double dAlphaTheta = alpha * dTheta;
    double dBeta = M_PI - dGamma - dAlphaTheta;

    alpha = sin(dAlphaTheta) / sin(dBeta) / dCartLength;

    double dX = vecNodes[ix0].x + (vecNodes[ix1].x - vecNodes[ix0].x) * alpha;
    double dY = vecNodes[ix0].y + (vecNodes[ix1].y - vecNodes[ix0].y) * alpha;
    double dZ = vecNodes[ix0].z + (vecNodes[ix1].z - vecNodes[ix0].z) * alpha;

    // Project to sphere
    double dRadius = sqrt(dX*dX + dY*dY + dZ*dZ);

    dX /= dRadius;
    dY /= dRadius;
    dZ /= dRadius;

    // Index
    int ix = vecNodes.size();

    // Insert node
    vecNodes.push_back(Node(dX, dY, dZ));

    return ix;
}
Exemple #13
0
/* CENTRAL METHOD to parse and render html request*/
int handle(cchar* q0,int conn){
	int len=(int)strlen(q0);
	if(len>1000){
		p("checkSanity len>1000");
		return 0;// SAFETY!
	}
    char* q=editable(q0);
	checkSanity(q,len);
    while(q[0]=='/')q++;
	enum result_format format = html;//txt; html DANGER WITH ROBOTS
	enum result_verbosity verbosity = normal;

	if (eq(q, "favicon.ico"))return 0;
    if(contains(q,"robots.txt")){
        Writeline(conn,"User-agent: *\n");
        Writeline("Disallow: /\n");
        return 0;
    }
	
	char* jsonp=strstr(q,"jsonp");// ?jsonp=fun
	if(jsonp){
		jsonp[-1]=0;
		jsonp+=6;
		format = json;
		}
	else jsonp=(char*)"parseResults";

	if (endsWith(q, ".json")) {
        format = json;
        q[len-5]=0;
    }
    
	if (endsWith(q, ".xml")) {
        format = xml;
        q[len-4]=0;
    }
    
	if (endsWith(q, ".csv")||endsWith(q, ".tsv")) {
        format = csv;
        q[len-4]=0;
    }
    
	if (endsWith(q, ".txt")) {
        format = txt;
        q[len-4]=0;
    }
    
	if (endsWith(q, ".html")) {
		format = html;
		q[len-5]=0;
	}
	if (startsWith(q, ".js")) {
		q[len-3]=0;
		Writeline(conn, jsonp);
		Writeline(conn, "(");
		format = js;
	}
	// todo : dedup!!
	if (startsWith(q, "all/")) {
		cut_to(q," +");
		cut_to(q," -");
		q = q + 4;
		showExcludes=false;
		verbosity = alle;
	}
	if (startsWith(q, "long/")){
		verbosity =  longer;
		q = q + 5;
	}
	if (startsWith(q, "full/")) {
		verbosity =  verbose;
		q = q + 5;
	}
	if (startsWith(q, "verbose/")) {
		verbosity = verbose;
		q = q + 8;
	}
	if (startsWith(q, "short/")) {
		verbosity = shorter;
		q = q + 6;
	}

	if (startsWith(q, "html/")) {
        format = html;
        if(!contains(q,".")&&!contains(q,":"))
			verbosity=verbose;
        q = q + 5;
    }
	if (startsWith(q, "plain/")) {
		format = txt;
		q = q + 6;
	}
	if (startsWith(q, "text/")) {
		format = txt;
		q = q + 5;
	}
	if (startsWith(q, "txt/")) {
		format = txt;
		q = q + 4;
	}
	if (startsWith(q, "xml/")) {
		format = xml;
		q = q + 4;
	}
	if (startsWith(q, "csv/")||startsWith(q, "tsv/")) {
		format = csv;
		q = q + 4;
	}
	if (startsWith(q, "json/")) {
		format = json;
		q = q + 5;
	}
	if (startsWith(q, "js/")) {
		q = q + 3;
		Writeline(conn, jsonp);
		Writeline(conn, "(");
		format = js;
	}
	if (startsWith(q, "long/")) {
		verbosity = longer;
		q = q + 5;
	}
	if (startsWith(q, "verbose/")) {
		verbosity = verbose;
		q = q + 8;
	}
	if (startsWith(q, "short/")) {
		verbosity = shorter;
		q = q + 6;
	}
	if (startsWith(q, "excludes/")||startsWith(q, "includes/")||startsWith(q, "excluded/")||startsWith(q, "included/")||startsWith(q, "showview/")) {
        showExcludes=true;
        verbosity=longer;
		q = q + 9;
	}
    else showExcludes=false;
    excluded.clear();
    included.clear();
    
    if(contains(q,"statement count")){Writeline(conn,itoa((int)context->statementCount).data());return 0;}
    if(contains(q,"node count")){Writeline(conn,itoa(context->nodeCount).data());return 0;}
    
    
	if (startsWith(q, "all/")) {
        cut_to(q," +");
        cut_to(q," -");
		q = q + 4;
		showExcludes=false;
		verbosity = alle;
	}
//	bool get_topic=false;
	bool get_topic=true;
	bool sort=false;
	if (startsWith(q, "ee/")||startsWith(q, "ee ")) {
		q[2]=' ';
		get_topic=true;
	}
	if (startsWith(q, "entities/")) {
		q[8]=' ';
		get_topic=true;
//		verbosity=longer;
	}
	if(hasWord(q)) loadView(q);
    
    if(contains(q,"exclude")||contains(q,"include")){
        verbosity=normal;
        showExcludes=true;
    }
	p(q);
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!
	//
    NodeVector all = parse(q); // <<<<<<<< HANDLE QUERY WITH NETBASE!
    //
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!

	autoIds=false;
    int size=(int)all.size();
    if(showExcludes){
        for (int i = 0; i < size; i++) {
        // todo : own routine!!!
        Node* node = (Node*) all[i];
        if(!contains(all,getAbstract(node->name)))
            all.push_back(getAbstract(node->name));
        N parent= getType(node);
        if(parent){
            if(!contains(all,parent))all.push_back(parent);
            N abs= getAbstract(parent->name);
            if(parent&&!contains(all,abs))all.push_back(abs);
        }
        }
        show(excluded);
    }
    
    const char* html_block="<!DOCTYPE html><html><head><META HTTP-EQUIV='CONTENT-TYPE' CONTENT='text/html; charset=UTF-8'/></head>"\
							"<body><div id='netbase_results'></div>\n<script>var results=";
    //    if((int)all.size()==0)Writeline("0");
	//	Writeline(conn,q);
	char buff[10000];

	bool use_json= format == json || format == js || format == html;
	if (format == xml && (startsWith(q,"select")||contains(q," where "))){Writeline(conn,query2(q));return 0;}
	if (format == xml)Writeline(conn, "<results>\n");
	if (format == html)Writeline(conn,html_block);
	if (use_json)Writeline(conn, "{\"results\":[\n");
	const char* statement_format_xml = "   <statement id='%d' subject=\"%s\" predicate=\"%s\" object=\"%s\" sid='%d' pid='%d' oid='%d'/>\n";
	const char* statement_format_text = "   $%d %s %s %s %d->%d->%d\n";
	const char* statement_format_json = "      { \"id\":%d, \"subject\":\"%s\", \"predicate\":\"%s\", \"object\":\"%s\", \"sid\":%d, \"pid\":%d, \"oid\":%d}";
	const char* statement_format_csv = "%d\t%s\t%s\t%s\t%d\t%d\t%d\n";
	const char* statement_format = 0;
	if (format == xml)statement_format = statement_format_xml;
	if (format == html)statement_format = statement_format_json;
	if (format == json)statement_format = statement_format_json;
	if (format == txt)statement_format = statement_format_text;
	if (format == csv)statement_format = statement_format_csv;
    
	const char* entity_format = 0;
	const char* entity_format_txt = "%s #%d (statements:%d) %s\n";
	const char* entity_format_xml = "<entity name=\"%s\" id='%d' statementCount='%d' description='%s'>\n";
	const char* entity_format_json = "   {\"name\":\"%s\", \"id\":%d, \"statementCount\":%d, \"description\":\"%s\"";
   	const char* entity_format_csv = "%s\t%d\t%d\t%s\n";
    if(all.size()==1)entity_format_csv = "";//statements!
	if (format == xml)entity_format = entity_format_xml;
	if (format == txt)entity_format = entity_format_txt;
	if (format == csv)entity_format = entity_format_csv;
	if (use_json)	  entity_format = entity_format_json;
	Node* last=0;
    warnings=0;
    char* entity=0;
    if(startsWith(q,"all")){
        entity=(char*)cut_to(q," ");
        entity=keep_to(entity,"limit");
    }
   	sortNodes(all);
	int count=(int)all.size();
	int good=0;
	for (int i = 0; i < count && i<resultLimit; i++) {
		Node* node = (Node*) all[i];
		if(!checkNode(node))continue;
		if(node->id==0)continue;
		if(last==node)continue;
		if(eq(node->name,"◊"))continue;
		last=node;
        if(verbosity ==normal && entity&& eq(entity,node->name))continue;
		char* text=getText(node);
//		if(use_json && get_topic){
//			if(empty(text))continue;//! no description = no entity? BAD for amazon etc
//			if(isAbstract(node))continue;
//			N t=getTopic(node);
//		}
		good++;
		if (use_json)if(good>1)Writeline(conn, "},\n");
		sprintf(buff, entity_format, node->name, node->id,node->statementCount,text);
		Writeline(conn, buff);
//        if(verbosity != alle && !get_topic)
//			loadView(node);
		bool got_topic=false;
		if(use_json && get_topic){
			N c=getClass(node);
			N t=getTopic(node);
			N ty=getType(node);
//			if(!c)c=t;
			if(!t)t=ty;
			if(t==node)t=ty;
			if(t!=Entity && checkNode(t)){
				got_topic=true;
				Writeline(conn, ",\n\t \"topicid\":"+itoa(t->id));
				Writeline(conn, ", \"topic\":\""+string(t->name)+"\"");
			}
			if(c && c!=t){
				Writeline(conn, ",\n\t \"classid\":"+itoa(c->id));
				Writeline(conn, ", \"class\":\""+string(c->name)+"\"");
			}
			if(ty&& c!=ty && ty!=t){
				Writeline(conn, ",\n\t \"typeid\":"+itoa(ty->id));
				Writeline(conn, ", \"type\":\""+string(ty->name)+"\"");
			}
		}
		if(use_json)// && (verbosity==verbose||verbosity==shorter))// lol // just name
			Writeline(conn, ", \"kind\":"+itoa(node->kind));
		if((use_json)&&!showExcludes&&node->statementCount>1 && getImage(node)!="")
			Writeline(", \"image\":\""+replace_all(replace_all(getImage(node,150,/*thumb*/true),"'","%27"),"\"","%22")+"\"");
//		if((use_json)&&getText(node)[0]!=0)
//			Writeline(", \"description\":\""+string(getText(node))+"\"");
		Statement* s = 0;
		if (format==csv|| verbosity == verbose || verbosity == longer|| verbosity == alle || showExcludes || ( all.size() == 1 && !(verbosity == shorter))) {
			int count=0;
            //            Writeline(",image:\""+getImage(node->name)+"\"");
			if (use_json)Writeline(conn, ",\n\t \"statements\":[\n");

//			sortStatements(
			deque<Statement*> statements;// sort
			while ((s = nextStatement(node, s))&&count++<lookupLimit){// resultLimit
				if (!checkStatement(s))break;
//				if(!got_topic &&( s->predicate==_Type|| s->predicate==_SuperClass)){
//					addStatementToNode(node, s->id(), true);// next time
//				}
				if(get_topic &&!got_topic && verbosity != verbose && (s->predicate>100 || s->predicate<-100))
					continue;// only important stuff here!
				// filter statements

				if(s->object==0)continue;
//				if(eq(s->Predicate()->name,"Offizielle Website") && !contains(s->Object()->name,"www"))
//					continue;
				if (s->subject==node->id and s->predicate!=4)//_instance
					statements.push_front(s);
				else statements.push_back(s);
			}
//			if(get_topic && verbosity!=shorter){
//				NV topics=getTopics(node);
//				N s=topics[0];
//				for (int j = 0; j < topics.size() && j<=resultLimit; j++) {
//					N s=topics[j];
//					Temporary statement (node,topic,s)
//					statements.push_front(s);
//				}
//			}




			int good=0;
			for (int j = 0; j < statements.size() && j<=resultLimit; j++) {
				s=statements.at(j);
//			while ((s = nextStatement(node, s))&&count++<resultLimit) {
                if(format==csv&&all.size()>1)break;// entities vs statements
                p(s);
				if(verbosity!=alle&&checkHideStatement(s)){warnings++;continue;}
				fixLabels(s);
				if(!(verbosity==verbose||verbosity==alle) && (s->Predicate()==Instance||s->Predicate()==Type))continue;
				if(use_json && good>0)Writeline(conn, ",\n");
				char* objectName=s->Object()->name;

				if(s->Predicate()==Instance){
					N type=findProperty(s->Object(),Type->name,0,50);
					if(  checkNode(type))
						objectName=(char*)(concat(concat(objectName, ": "),type->name));
				}
				sprintf(buff, statement_format, s->id(), s->Subject()->name, s->Predicate()->name, objectName, s->Subject()->id, s->Predicate()->id, s->Object()->id);
				Writeline(conn, buff);
				good++;
			}
			if (use_json)Writeline(conn, "]");
		}
		if (format == xml)Writeline(conn, "</entity>\n");
		//		string img=getImage(node->name);
		//		if(img!="")Writeline(conn,"<img src=\""+img+"\"/>");
	}

	if (use_json || format == html || format == js)Writeline(conn,good>0?"}\n]}":"]}");
	if (format == xml)Writeline(conn, "</results>\n");
	if(format == js)Writeline(conn, ")");// jsonp
		const char* html_end=";\n</script>\n<script src='http://pannous.net/netbase.js'></script></body></html>\n";
	if(format == html)Writeline(conn, html_end);
	//		sprintf(buff,	"<script src='/js/%s'></script>",q0);
	//		Writeline(conn, buff);
	//	}
    pf("Warnings/excluded: %d\n",warnings);
    return 0;// 0K
}
Exemple #14
0
void ImdReader::ReadModel(const char *pszFilename) {
    CPLDebug( "OGR_ILI", "Reading model '%s'", pszFilename);

    CPLXMLNode* psRootNode = CPLParseXMLFile(pszFilename);
    if( psRootNode == NULL )
        return;
    CPLXMLNode *psSectionNode = CPLGetXMLNode( psRootNode, "=TRANSFER.DATASECTION" );
    if( psSectionNode == NULL )
        return;

    StrNodeMap oTidLookup; /* for fast lookup of REF relations */
    ClassesMap oClasses;
    NodeCountMap oAxisCount;
    NodeVector oArcLineTypes;
    const char *modelName;

    /* Fill TID lookup map and IliClasses lookup map */
    CPLXMLNode* psModel = psSectionNode->psChild;
    while( psModel != NULL )
    {
        modelName = CPLGetXMLValue( psModel, "BID", NULL );
        //CPLDebug( "OGR_ILI", "Model: '%s'", modelName);

        CPLXMLNode* psEntry = psModel->psChild;
        while( psEntry != NULL )
                {
            if (psEntry->eType != CXT_Attribute) //ignore BID
            {
                //CPLDebug( "OGR_ILI", "Node tag: '%s'", psEntry->pszValue);
                const char* psTID = CPLGetXMLValue( psEntry, "TID", NULL );
                if( psTID != NULL )
                    oTidLookup[psTID] = psEntry;


                if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.Model") && !EQUAL(modelName, "MODEL.INTERLIS"))
                {
                    IliModelInfo modelInfo;
                    modelInfo.name = CPLGetXMLValue( psEntry, "Name", "OGR" );
                    modelInfo.version = CPLGetXMLValue( psEntry, "Version", "" );
                    modelInfo.uri = CPLGetXMLValue( psEntry, "At", "" );
                    modelInfos.push_back(modelInfo);
                    mainModelName = modelInfo.name; //FIXME: check model inheritance
                    //version = CPLGetXMLValue(psEntry, "iliVersion", "0"); //1 or 2.3

                    CPLXMLNode *psFormatNode = CPLGetXMLNode( psEntry, "ili1Format" );
                    if (psFormatNode != NULL)
                    {
                        psFormatNode = psFormatNode->psChild;
                        codeBlank = atoi(CPLGetXMLValue(psFormatNode, "blankCode", "95"));
                        codeUndefined = atoi(CPLGetXMLValue(psFormatNode, "undefinedCode", "64"));
                        codeContinue = atoi(CPLGetXMLValue(psFormatNode, "continueCode", "92"));
                    }
                }
                else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.SubModel"))
                {
                    mainBasketName = CPLGetXMLValue(psEntry, "TID", "OGR");
                    mainTopicName = CPLGetXMLValue(psEntry, "Name", "OGR");
                }
                else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.Class") )
                {
                    CPLDebug( "OGR_ILI", "Class name: '%s'", psTID);
                    oClasses[psEntry] = new IliClass(psEntry, iliVersion, oTidLookup, oClasses, oAxisCount);
                }
            }
            psEntry = psEntry->psNext;
        }

        // 2nd pass: add fields via TransferElement entries & role associations
        psEntry = psModel->psChild;
        while( psEntry != NULL )
        {
            if (psEntry->eType != CXT_Attribute) //ignore BID
            {
                //CPLDebug( "OGR_ILI", "Node tag: '%s'", psEntry->pszValue);
                if( iliVersion == 1 && EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.Ili1TransferElement"))
                {
                    const char* psClassRef = CPLGetXMLValue( psEntry, "Ili1TransferClass.REF", NULL );
                    const char* psElementRef = CPLGetXMLValue( psEntry, "Ili1RefAttr.REF", NULL );
                    int iOrderPos = atoi(CPLGetXMLValue( psEntry, "Ili1RefAttr.ORDER_POS", "0" ))-1;
                    IliClass* psParentClass = oClasses[oTidLookup[psClassRef]];
                    CPLXMLNode* psElementNode = oTidLookup[psElementRef];
                    psParentClass->AddFieldNode(psElementNode, iOrderPos);
                }
                else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.TransferElement"))
                {
                    const char* psClassRef = CPLGetXMLValue( psEntry, "TransferClass.REF", NULL );
                    const char* psElementRef = CPLGetXMLValue( psEntry, "TransferElement.REF", NULL );
                    int iOrderPos = atoi(CPLGetXMLValue( psEntry, "TransferElement.ORDER_POS", "0" ))-1;
                    IliClass* psParentClass = oClasses[oTidLookup[psClassRef]];
                    CPLXMLNode* psElementNode = oTidLookup[psElementRef];
                    psParentClass->AddFieldNode(psElementNode, iOrderPos);
                }
                else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.Role"))
                {
                    const char* psRefParent = CPLGetXMLValue( psEntry, "Association.REF", NULL );
                    int iOrderPos = atoi(CPLGetXMLValue( psEntry, "Association.ORDER_POS", "0" ))-1;
                    IliClass* psParentClass = oClasses[oTidLookup[psRefParent]];
                    if (psParentClass)
                        psParentClass->AddRoleNode(psEntry, iOrderPos);
                }
                else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.AxisSpec"))
                {
                    const char* psClassRef = CPLGetXMLValue( psEntry, "CoordType.REF", NULL );
                    //int iOrderPos = atoi(CPLGetXMLValue( psEntry, "Axis.ORDER_POS", "0" ))-1;
                    CPLXMLNode* psCoordTypeNode = oTidLookup[psClassRef];
                    oAxisCount[psCoordTypeNode] += 1;
                }
                else if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.LinesForm"))
                {
                    const char* psLineForm = CPLGetXMLValue( psEntry, "LineForm.REF", NULL );
                    if (EQUAL(psLineForm, "INTERLIS.ARCS")) {
                        const char* psElementRef = CPLGetXMLValue( psEntry, "LineType.REF", NULL );
                        CPLXMLNode* psElementNode = oTidLookup[psElementRef];
                        oArcLineTypes.push_back(psElementNode);
                    }
                }
            }
            psEntry = psEntry->psNext;

        }

        psModel = psModel->psNext;
    }

    /* Analyze class inheritance & add fields to class table defn */
    for (ClassesMap::const_iterator it = oClasses.begin(); it != oClasses.end(); ++it)
    {
        //CPLDebug( "OGR_ILI", "Class: '%s'", it->second->GetName());
        const char* psRefSuper = CPLGetXMLValue( it->first, "Super.REF", NULL );
        if (psRefSuper) {
            if (oTidLookup.find(psRefSuper) != oTidLookup.end() &&
                oClasses.find(oTidLookup[psRefSuper]) != oClasses.end()) {
                oClasses[oTidLookup[psRefSuper]]->hasDerivedClasses = true;
            } else {
                CPLError(CE_Warning, CPLE_AppDefined,
                    "Couldn't reference super class '%s'", psRefSuper);
            }
        }
        it->second->InitFieldDefinitions();
        it->second->AddFieldDefinitions(oArcLineTypes);
    }

    /* Filter relevant classes */
    for (ClassesMap::const_iterator it = oClasses.begin(); it != oClasses.end(); ++it)
    {
        const char* className = it->second->GetIliName();
        FeatureDefnInfo oClassInfo = it->second->tableDefs();
        if (!EQUALN(className, "INTERLIS.", 9) && oClassInfo.poTableDefn)
            featureDefnInfos.push_back(oClassInfo);
    }

    CPLDestroyXMLNode(psRootNode);
}