text:
using System;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Data;
using System.ComponentModel;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Linq.Expressions;

namespace S11Context
{

    /// <summary>
    /// элемент субклассификации МКБ по 5 знаку
    /// </summary>
    [Table(Name = @"s11.rbMKBSubclass_Item")]
    public partial class RbMKBSubclassItem : INotifyPropertyChanging, INotifyPropertyChanged
    {

        private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(System.String.Empty);

        private int _Id;

        private System.DateTime _CreateDatetime;

        private System.Nullable<int> _CreatePersonId;

        private System.DateTime _ModifyDatetime;

        private System.Nullable<int> _ModifyPersonId;

        private int _MasterId;

        private string _Code;

        private string _Name;

        private EntityRef<Person> _Person_CreatePersonId;

        private EntityRef<Person> _Person_ModifyPersonId;

        private EntityRef<RbMKBSubclass> _RbMKBSubclass;

        #region Extensibility Method Definitions
        partial void OnLoaded();
        partial void OnValidate(System.Data.Linq.ChangeAction action);
        partial void OnCreated();
        partial void OnIdChanging(int value);
        partial void OnIdChanged();
        partial void OnCreateDatetimeChanging(System.DateTime value);
        partial void OnCreateDatetimeChanged();
        partial void OnCreatePersonIdChanging(System.Nullable<int> value);
        partial void OnCreatePersonIdChanged();
        partial void OnModifyDatetimeChanging(System.DateTime value);
        partial void OnModifyDatetimeChanged();
        partial void OnModifyPersonIdChanging(System.Nullable<int> value);
        partial void OnModifyPersonIdChanged();
        partial void OnMasterIdChanging(int value);
        partial void OnMasterIdChanged();
        partial void OnCodeChanging(string value);
        partial void OnCodeChanged();
        partial void OnNameChanging(string value);
        partial void OnNameChanged();
        #endregion

        public RbMKBSubclassItem()
        {
            this._Person_CreatePersonId  = default(EntityRef<Person>);
            this._Person_ModifyPersonId  = default(EntityRef<Person>);
            this._RbMKBSubclass  = default(EntityRef<RbMKBSubclass>);
            OnCreated();
        }

        /// <summary>
        /// There are no comments for Id in the schema.
        /// </summary>
        [Column(Name = @"id", Storage = "_Id", AutoSync = AutoSync.OnInsert, CanBeNull = false, DbType = "INT(10) NOT NULL AUTO_INCREMENT", IsDbGenerated = true, IsPrimaryKey = true)]
        public int Id
        {
            get
            {
                return this._Id;
            }
            set
            {
                if (this._Id != value)
                {
                    this.OnIdChanging(value);
                    this.SendPropertyChanging();
                    this._Id = value;
                    this.SendPropertyChanged("Id");
                    this.OnIdChanged();
                }
            }
        }

        /// <summary>
        /// Дата создания записи
        /// </summary>
        [Column(Name = @"createDatetime", Storage = "_CreateDatetime", CanBeNull = false, DbType = "DATETIME NOT NULL")]
        public System.DateTime CreateDatetime
        {
            get
            {
                return this._CreateDatetime;
            }
            set
            {
                if (this._CreateDatetime != value)
                {
                    this.OnCreateDatetimeChanging(value);
                    this.SendPropertyChanging();
                    this._CreateDatetime = value;
                    this.SendPropertyChanged("CreateDatetime");
                    this.OnCreateDatetimeChanged();
                }
            }
        }

        /// <summary>
        /// Автор записи {Person}
        /// </summary>
        [Column(Name = @"createPerson_id", Storage = "_CreatePersonId", DbType = "INT(10)")]
        public System.Nullable<int> CreatePersonId
        {
            get
            {
                return this._CreatePersonId;
            }
            set
            {
                if (this._CreatePersonId != value)
                {
                    if (this._Person_CreatePersonId.HasLoadedOrAssignedValue)
                    {
                        throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException();
                    }

                    this.OnCreatePersonIdChanging(value);
                    this.SendPropertyChanging();
                    this._CreatePersonId = value;
                    this.SendPropertyChanged("CreatePersonId");
                    this.OnCreatePersonIdChanged();
                }
            }
        }

        /// <summary>
        /// Дата изменения записи
        /// </summary>
        [Column(Name = @"modifyDatetime", Storage = "_ModifyDatetime", CanBeNull = false, DbType = "DATETIME NOT NULL")]
        public System.DateTime ModifyDatetime
        {
            get
            {
                return this._ModifyDatetime;
            }
            set
            {
                if (this._ModifyDatetime != value)
                {
                    this.OnModifyDatetimeChanging(value);
                    this.SendPropertyChanging();
                    this._ModifyDatetime = value;
                    this.SendPropertyChanged("ModifyDatetime");
                    this.OnModifyDatetimeChanged();
                }
            }
        }

        /// <summary>
        /// Автор изменения записи {Person}
        /// </summary>
        [Column(Name = @"modifyPerson_id", Storage = "_ModifyPersonId", DbType = "INT(10)")]
        public System.Nullable<int> ModifyPersonId
        {
            get
            {
                return this._ModifyPersonId;
            }
            set
            {
                if (this._ModifyPersonId != value)
                {
                    if (this._Person_ModifyPersonId.HasLoadedOrAssignedValue)
                    {
                        throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException();
                    }

                    this.OnModifyPersonIdChanging(value);
                    this.SendPropertyChanging();
                    this._ModifyPersonId = value;
                    this.SendPropertyChanged("ModifyPersonId");
                    this.OnModifyPersonIdChanged();
                }
            }
        }

        /// <summary>
        /// {rbMKBSubclass}
        /// </summary>
        [Column(Name = @"master_id", Storage = "_MasterId", CanBeNull = false, DbType = "INT(10) NOT NULL")]
        public int MasterId
        {
            get
            {
                return this._MasterId;
            }
            set
            {
                if (this._MasterId != value)
                {
                    if (this._RbMKBSubclass.HasLoadedOrAssignedValue)
                    {
                        throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException();
                    }

                    this.OnMasterIdChanging(value);
                    this.SendPropertyChanging();
                    this._MasterId = value;
                    this.SendPropertyChanged("MasterId");
                    this.OnMasterIdChanged();
                }
            }
        }

        /// <summary>
        /// пятый знак
        /// </summary>
        [Column(Name = @"code", Storage = "_Code", CanBeNull = false, DbType = "VARCHAR(8) NOT NULL")]
        public string Code
        {
            get
            {
                return this._Code;
            }
            set
            {
                if (this._Code != value)
                {
                    this.OnCodeChanging(value);
                    this.SendPropertyChanging();
                    this._Code = value;
                    this.SendPropertyChanged("Code");
                    this.OnCodeChanged();
                }
            }
        }

        /// <summary>
        /// наименование
        /// </summary>
        [Column(Name = @"name", Storage = "_Name", CanBeNull = false, DbType = "VARCHAR(128) NOT NULL")]
        public string Name
        {
            get
            {
                return this._Name;
            }
            set
            {
                if (this._Name != value)
                {
                    this.OnNameChanging(value);
                    this.SendPropertyChanging();
                    this._Name = value;
                    this.SendPropertyChanged("Name");
                    this.OnNameChanged();
                }
            }
        }

        /// <summary>
        /// There are no comments for Person_CreatePersonId in the schema.
        /// </summary>
        [Devart.Data.Linq.Mapping.Association(Name="Person_Id_RbMKBSubclassItem_CreatePersonId", Storage="_Person_CreatePersonId", ThisKey="CreatePersonId", IsForeignKey=true)]
        public Person Person_CreatePersonId
        {
            get
            {
                return this._Person_CreatePersonId.Entity;
            }
            set
            {
                Person previousValue = this._Person_CreatePersonId.Entity;
                if ((previousValue != value) || (this._Person_CreatePersonId.HasLoadedOrAssignedValue == false))
                {
                    this.SendPropertyChanging();
                    if (previousValue != null)
                    {
                        this._Person_CreatePersonId.Entity = null;
                        previousValue.RbMKBSubclassItems_CreatePersonId.Remove(this);
                    }
                    this._Person_CreatePersonId.Entity = value;
                    if (value != null)
                    {
                        this._CreatePersonId = value.Id;
                        value.RbMKBSubclassItems_CreatePersonId.Add(this);
                    }
                    else
                    {
                        this._CreatePersonId = default(System.Nullable<int>);
                    }
                    this.SendPropertyChanged("Person_CreatePersonId");
                }
            }
        }

        /// <summary>
        /// There are no comments for Person_ModifyPersonId in the schema.
        /// </summary>
        [Devart.Data.Linq.Mapping.Association(Name="Person_Id_RbMKBSubclassItem_ModifyPersonId", Storage="_Person_ModifyPersonId", ThisKey="ModifyPersonId", IsForeignKey=true)]
        public Person Person_ModifyPersonId
        {
            get
            {
                return this._Person_ModifyPersonId.Entity;
            }
            set
            {
                Person previousValue = this._Person_ModifyPersonId.Entity;
                if ((previousValue != value) || (this._Person_ModifyPersonId.HasLoadedOrAssignedValue == false))
                {
                    this.SendPropertyChanging();
                    if (previousValue != null)
                    {
                        this._Person_ModifyPersonId.Entity = null;
                        previousValue.RbMKBSubclassItems_ModifyPersonId.Remove(this);
                    }
                    this._Person_ModifyPersonId.Entity = value;
                    if (value != null)
                    {
                        this._ModifyPersonId = value.Id;
                        value.RbMKBSubclassItems_ModifyPersonId.Add(this);
                    }
                    else
                    {
                        this._ModifyPersonId = default(System.Nullable<int>);
                    }
                    this.SendPropertyChanged("Person_ModifyPersonId");
                }
            }
        }

        /// <summary>
        /// There are no comments for RbMKBSubclass in the schema.
        /// </summary>
        [Devart.Data.Linq.Mapping.Association(Name="RbMKBSubclass_RbMKBSubclassItem", Storage="_RbMKBSubclass", ThisKey="MasterId", IsForeignKey=true)]
        public RbMKBSubclass RbMKBSubclass
        {
            get
            {
                return this._RbMKBSubclass.Entity;
            }
            set
            {
                RbMKBSubclass previousValue = this._RbMKBSubclass.Entity;
                if ((previousValue != value) || (this._RbMKBSubclass.HasLoadedOrAssignedValue == false))
                {
                    this.SendPropertyChanging();
                    if (previousValue != null)
                    {
                        this._RbMKBSubclass.Entity = null;
                        previousValue.RbMKBSubclassItems.Remove(this);
                    }
                    this._RbMKBSubclass.Entity = value;
                    if (value != null)
                    {
                        this._MasterId = value.Id;
                        value.RbMKBSubclassItems.Add(this);
                    }
                    else
                    {
                        this._MasterId = default(int);
                    }
                    this.SendPropertyChanged("RbMKBSubclass");
                }
            }
        }

        public event PropertyChangingEventHandler PropertyChanging;

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void SendPropertyChanging()
        {
            if (this.PropertyChanging != null)
                this.PropertyChanging(this, emptyChangingEventArgs);
        }

        protected virtual void SendPropertyChanging(System.String propertyName)
        {
            if (this.PropertyChanging != null)
                this.PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
        }

        protected virtual void SendPropertyChanged(System.String propertyName)
        {
             if (this.PropertyChanged != null)
                 this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}


text:
package com.cisco.app.dbmigrator.migratorapp.logging.connection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.bson.Document;
import org.bson.codecs.Codec;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
import org.slf4j.LoggerFactory;

import com.cisco.app.dbmigrator.migratorapp.config.SyncConfig;
import com.cisco.app.dbmigrator.migratorapp.constants.SyncConstants;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.MngToOrclEventCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.MngToOrclMapCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.MngToOrclSyncEventCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.O2MSyncEventLogCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.OrclToMngEventCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.OrclToMngGridFsEventCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.OrclToMngMapCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.OrclToMngSyncEventCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.OrclToMongoGridFsMapCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.SyncConnectionInfoCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.SyncErrorCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.SyncEventCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.SyncMapCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.SyncMarkerCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.SyncNodeCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.SyncNodeDetailsCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.SyncUserDetailCodec;
import com.cisco.app.dbmigrator.migratorapp.logging.codecs.SyncUserSessionCodec;
import com.cisco.app.dbmigrator.migratorapp.utilities.encrypt.EncryptorDecryptor;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.WriteConcern;
import com.mongodb.client.MongoDatabase;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;

public enum MongoConnection {
	INSTANCE;
	private MongoDatabase mongoDataBase;
	private final Logger logger;
	private final String ERR_MSG = "Error while initializing mongo client";

	public MongoDatabase getMongoDataBase() {
		return mongoDataBase;
	}

	private MongoConnection() {
		logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
		logger.info("Start Creating Connection Enum");

		logger.setLevel(getLogLevel());
		if (isSslEnabled()) {
			System.setProperty("javax.net.ssl.trustStore",
					SyncConfig.INSTANCE.getProperty(SyncConstants.TRUSTSTORE_PATH));
			System.setProperty("javax.net.ssl.trustStorePassword",
					SyncConfig.INSTANCE.getProperty(SyncConstants.TRUSTSTORE_PASS));
			System.setProperty("javax.net.ssl.keyStore", SyncConfig.INSTANCE.getProperty(SyncConstants.KEYSTORE_PATH));
			System.setProperty("javax.net.ssl.keyStorePassword",
					SyncConfig.INSTANCE.getProperty(SyncConstants.TRUSTSTORE_PASS));

		}

		Codec<Document> defaultDocumentCodec = MongoClient.getDefaultCodecRegistry().get(Document.class);

		CodecRegistry codecRegistry = CodecRegistries.fromRegistries(MongoClient.getDefaultCodecRegistry(),
				CodecRegistries.fromCodecs(new SyncMarkerCodec(defaultDocumentCodec),
						new OrclToMngSyncEventCodec(defaultDocumentCodec), new SyncErrorCodec(defaultDocumentCodec),
						new SyncUserDetailCodec(defaultDocumentCodec), new SyncUserSessionCodec(defaultDocumentCodec),
						new SyncConnectionInfoCodec(defaultDocumentCodec), new SyncNodeCodec(defaultDocumentCodec),
						new SyncEventCodec(defaultDocumentCodec), new SyncMapCodec(defaultDocumentCodec),
						new OrclToMngMapCodec(defaultDocumentCodec), new OrclToMngEventCodec(defaultDocumentCodec),
						new MngToOrclMapCodec(defaultDocumentCodec), new MngToOrclEventCodec(defaultDocumentCodec),
						new MngToOrclSyncEventCodec(defaultDocumentCodec),
						new O2MSyncEventLogCodec(defaultDocumentCodec), new SyncNodeDetailsCodec(defaultDocumentCodec),
						new OrclToMongoGridFsMapCodec(defaultDocumentCodec),
						new OrclToMngGridFsEventCodec(defaultDocumentCodec)));

		MongoClientOptions options = MongoClientOptions.builder().writeConcern(getWriteConcern())
				.sslEnabled(isSslEnabled()).sslInvalidHostNameAllowed(allowInvalidHosts()).codecRegistry(codecRegistry)
				.build();
		try {
			setMongoDataBase(options);
			logger.info("Connection Enum created");
		} catch (Exception e) {
			logger.error(ERR_MSG, e);
		}
	}

	private WriteConcern getWriteConcern() {
		WriteConcern writeConcern = null;
		try {
			String writeConcernProp = SyncConfig.INSTANCE.getProperty(SyncConstants.WRITE_CONCERN);
			if (writeConcernProp != null && !writeConcernProp.isEmpty()) {
				logger.info("Write Concern loaded from DB : " + writeConcernProp);
				writeConcern = WriteConcern.valueOf(writeConcernProp);
			}
			if (writeConcern == null) {
				writeConcern = WriteConcern.MAJORITY;
			}
		} catch (Exception e) {
			logger.error("Error while setting WRITE_CONCERN from loaded configuration", e);
			writeConcern = WriteConcern.MAJORITY;
		}
		logger.info("Write Concern set as : " + writeConcern);
		return writeConcern;
	}

	private boolean isSslEnabled() {
		boolean isSslEnabled = false;
		try {
			String isSslEnabledProp = SyncConfig.INSTANCE.getProperty(SyncConstants.SSL_ENABLED);
			if (isSslEnabledProp != null && !isSslEnabledProp.isEmpty()) {
				logger.info("SSL_ENABLED value loaded from config : " + isSslEnabledProp);
				isSslEnabled = Boolean.valueOf(isSslEnabledProp);
			}
		} catch (Exception e) {
			logger.error("Error while retreiving SSL_ENABLED value from loaded configuration", e);
			isSslEnabled = false;
		}
		logger.info("SSL_ENABLED : " + isSslEnabled);
		return isSslEnabled;
	}

	private boolean allowInvalidHosts() {
		boolean allowInvalidHosts = false;
		try {
			String allowInvalidHostsProp = SyncConfig.INSTANCE.getProperty(SyncConstants.SSL_ALLOW_INVALID_HOST);
			if (allowInvalidHostsProp != null && !allowInvalidHostsProp.isEmpty()) {
				allowInvalidHosts = Boolean.valueOf(allowInvalidHostsProp);
			}
		} catch (Exception e) {
			allowInvalidHosts = false;
		}
		logger.info("ALLOW_INVALID_HOSTS : " + allowInvalidHosts);
		return allowInvalidHosts;
	}

	private Level getLogLevel() {
		String logLevel = SyncConfig.INSTANCE.getProperty(SyncConstants.LOGGING_LEVEL);
		logger.debug("Mongo Logger level configured to : " + logLevel);
		Level level = Level.toLevel(logLevel, Level.DEBUG);
		return level;
	}

	private boolean isPwdEncrypted() {
		boolean isPwdEncrypted = false;
		String encryptedProp = SyncConfig.INSTANCE.getDbProperty(SyncConstants.IS_PWD_ENCRYPTED);
		if (encryptedProp != null && !encryptedProp.isEmpty()) {
			isPwdEncrypted = Boolean.valueOf(encryptedProp);
		}
		logger.info("Password encryption flag is : "+isPwdEncrypted);
		return isPwdEncrypted;
	}

	private String getPassword() throws Exception {
		if (isPwdEncrypted()) {
			return EncryptorDecryptor.decrypt(SyncConfig.INSTANCE.getDbProperty(SyncConstants.PASSWORD),
					SyncConfig.INSTANCE.getDbProperty(SyncConstants.ENCRYPTION_KEY));
		} else {
			return SyncConfig.INSTANCE.getDbProperty(SyncConstants.PASSWORD);
		}
	}

	private void setMongoDataBase(MongoClientOptions options) throws Exception {
		List<ServerAddress> addressList = null;
		List<MongoCredential> credList = null;
		MongoCredential credential = null;
		String life = SyncConfig.INSTANCE.getProperty(SyncConstants.LIFE);
		logger.info("Loading DB Properties for " + life);
		SyncConfig config = SyncConfig.INSTANCE;
		String dbname = config.getDbProperty(SyncConstants.DBNAME);
		String username = config.getDbProperty(SyncConstants.USERNAME);
		int port = Integer.valueOf(config.getDbProperty(SyncConstants.PORT));
		String[] hostList = config.getDbProperty(SyncConstants.HOST).split(",");
		String pwd = getPassword();
		if (pwd != null && !pwd.isEmpty()) {
			credential = MongoCredential.createCredential(username, dbname, pwd.toCharArray());
			credList = Arrays.asList(credential);
		}

		if (hostList != null && hostList.length > 0) {
			addressList = new ArrayList<ServerAddress>();
			for (String hostName : hostList) {
				addressList.add(new ServerAddress(hostName, port));
			}
		}

		if (credList != null) {
			mongoDataBase = new MongoClient(addressList, credList, options).getDatabase(dbname);
		} else {
			mongoDataBase = new MongoClient(addressList, options).getDatabase(dbname);
		}
	}
}

redpajama_set_name: RedPajamaGithub


text:
"""

How to Find Niche Solutions
===========================

### Why Niche?

When exploring complex multi-objective surfaces, it
is trite to summarize that space with one number
such _max distance from hell_ (where _hell_ is the
point in objective space where all goals have their
worse values). For example, all the following points
have the same _distance from hell_, but they reflect
very different solutions:

[[etc/img/gunsbutter.png]]

A better way to do it is _niching_; i.e. generate
the Pareto frontier, then cluster that frontier and
report a (small) number of random samples from each
cluster.  In this approach, "distance from hell" can
still be used internally to guide a quick search for
places to expand the frontier. But after that, we
can isolate interesting different parts of the
solution space.

For example, when exploring options for configuring
London Ambulances, Veerappa and Letier  use optimization to
reject thousands of options (shown in red) in order
to isolate clusters of better solutions C1,C2,etc
(shown in green). In this example, the goal is to
minimize X and maximize Y .

[[etc/img/amus.png]]

(REF: V. Veerappa and E. Letier, "Understanding
 clusters of optimal solutions in multi-objective
 decision problems, in RE' 2011, Trento, Italy,
 2011, pp. 89-98.)

### What is a Niche?

According to Deb and Goldberg (1989) _a niche is
viewed as an organism's task in the environment and
a species is a collection of organisms with similar
features_.

+ REF: Kalyanmoy Deb and David
E. Goldberg. 1989.  [An Investigation of Niche and
Species Formation in Genetic Function
Optimization](http://goo.gl/oLIxo1). In
Proceedings of the 3rd International Conference on
Genetic Algorithms, J. David Schaffer (Ed.). Morgan
Kaufmann Publishers Inc., San Francisco, CA, USA,
42-50.

Their definition seems to suggest that niching means
clustering in objective space and species are the
things that form in each such cluster. Strange to
say, some of their examples report _niches_ using
decision space so all we can say is that it is an
engineering decision whether or not you _niche_ in
objective space or _niche_ in decision space. Note
that the above example from Veerappa and Letier
build niches in objective space while my code, shown
below, builds niches in decision space.

### How to Niche?

In any case, in decision or objective space, the
open issue is now to fun the niches? A naive
approach is to compute distances between all
individuals. This can be very slow, especially if
this calculation is called repeatedly deep inside
the inner-most loop of a program. In practice, any
program working with distance spends most of its
time computing those measures.  Various proposals
exist to prevent that happening:

+ _Canopy clustering_: McCallum, A.; Nigam, K.; and
   Ungar L.H. (2000) [ Efficient Clustering of High
   Dimensional Data Sets with Application to
   Reference Matching](http://goo.gl/xwIzN),
   Proceedings of the sixth ACM SIGKDD international
   conference on Knowledge discovery and data
   mining, 169-178
+ _Incremental stochastic k-means_ [Web-Scale
  K-Means Clustering](http://goo.gl/V8BQs),
  WWW 2010, April 26-30, 2010, Raleigh, North
  Carolina, USA.
+ _Triangle inequality tricks_ (which work very well
  indeed) [Making k-means Even Faster](http://goo.gl/hk3Emn).
  G Hamerly - 2010 SIAM International Conference on
  Data Mining.

My own favorite trick is WHERE, shown below. It uses
a data mining trick to recursively divide the space
of decisions in two, then four, then eight,
etc. REF: [Local vs. global lessons for defect
prediction and effort
estimation](http://menzies.us/pdf/12gense.pdf) T
Menzies, A Butcher, D Cok, A Marcus, L Layman, F
Shull, B Turhan, IEEE Transactions on Software
Engineering 29 (6), 822-834, 2012.

WHERE uses a linear-time trick (called the FastMap
heuristic) to find two distant solutions- these are
the _poles_ called _west_ and _east_. Note that the
following takes only _O(2N)_ distance calculations:

"""
def fastmap(m,data):
  "Divide data into two using distance to two distant items."
  one  = any(data)             # 1) pick anything
  west = furthest(m,one,data)  # 2) west is as far as you can go from anything
  east = furthest(m,west,data) # 3) east is as far as you can go from west
  c    = dist(m,west,east)
  # now find everyone's distance
  xsum, lst = 0.0,[]
  for one in data:
    a = dist(m,one,west)
    b = dist(m,one,east)
    x = (a*a + c*c - b*b)/(2*c) # cosine rule
    xsum += x
    lst  += [(x,one)]
  # now cut data according to the mean distance
  cut, wests, easts = xsum/len(data), [], []
  for x,one in lst:
    where = wests if x < cut else easts
    where += [one]
  return wests,west, easts,east
"""

In the above:

+ _m_ is some model that generates candidate
  solutions that we wish to niche.
+ _(west,east)_ are not _the_ most distant points
  (that would require _N*N) distance
  calculations). But they are at least very distant
  to each other.

This code needs some helper functions. _Dist_ uses
the standard Euclidean measure. Note that you tune
what it uses to define the niches (decisions or
objectives) using the _what_ parameter:

"""
def dist(m,i,j,
         what = lambda x: x.dec):
  "Euclidean distance 0 <= d <= 1 between decisions"
  d1,d2  = what(i), what(j)
  n      = len(d1)
  deltas = 0
  for d in range(n):
    n1 = norm(m, d, d1[d])
    n2 = norm(m, d, d2[d])
    inc = (n1-n2)**2
    deltas += inc
  return deltas**0.5 / n**0.5
"""

The _Dist_ function normalizes all the raw values zero to one.

"""
def norm(m,x,n) :
  "Normalizes value n on variable x within model m 0..1"
  return (n - lo(m,x)) / (hi(m,x) - lo(m,x) + 0.0001)
"""

Now we can define _furthest_:

"""
def furthest(m,i,all,
             init = 0,
             better = lambda x,y: x>y):
  "find which of all is furthest from 'i'"
  out,d= i,init
  for j in all:
    if not i == j:
      tmp = dist(m,i,j)
      if better(tmp,d): out,d = j,tmp
  return out
"""

WHERE finds everyone's else's distance from the poles
  and divide the data on the mean point of those
  distances.  This all stops if:

+  Any division has _tooFew_ solutions (say,
  less than _sqrt_ of the total number of
  solutions).
+ Something has gone horribly wrong and you are
  recursing _tooDeep_

This code is controlled by a set of _slots_.  For
example, if _slots.pruning_ is true, we may ignore
some sub-tree (this process is discussed, later on).
Also, if _slots.verbose_ is true, the _show_
function prints out a little tree showing the
progress (and to print indents in that tree, we use
the string _slots.b4_).  For example, here's WHERE
dividing 100 solutions:

    100
    |.. 50
    |.. |.. 25
    |.. |.. |.. 11
    |.. |.. |.. |.. 6.
    |.. |.. |.. |.. 5.
    |.. |.. |.. 14
    |.. |.. |.. |.. 6.
    |.. |.. |.. |.. 8.
    |.. |.. 25
    |.. |.. |.. 12
    |.. |.. |.. |.. 5.
    |.. |.. |.. |.. 7.
    |.. |.. |.. 13
    |.. |.. |.. |.. 5.
    |.. |.. |.. |.. 8.
    |.. 50
    |.. |.. 25
    |.. |.. |.. 13
    |.. |.. |.. |.. 7.
    |.. |.. |.. |.. 6.
    |.. |.. |.. 12
    |.. |.. |.. |.. 5.
    |.. |.. |.. |.. 7.
    |.. |.. 25
    |.. |.. |.. 11
    |.. |.. |.. |.. 5.
    |.. |.. |.. |.. 6.
    |.. |.. |.. 14
    |.. |.. |.. |.. 7.
    |.. |.. |.. |.. 7.

Here's the slots:

"""
class Slots():
  "Place to read/write named slots."
  id = -1
  def __init__(i,**d) :
    i.id = Slots.id = Slots.id + 1
    i.override(d)
  def override(i,d): i.__dict__.update(d); return i
  def __eq__(i,j)  : return i.id == j.id
  def __ne__(i,j)  : return i.id != j.id
  def __repr__(i)  : return '{' + showd(i.__dict__) + '}'

def where0(**other):
  return Slots(minSize  = 10,    # min leaf size
               depthMin= 2,      # no pruning till this depth
               depthMax= 10,     # max tree depth
               wriggle = 0.2,    # min difference of 'better'
               prune   = True,   # pruning enabled?
               b4      = '|.. ', # indent string
               verbose = False,  # show trace info?
               hedges  = 0.38    # strict=0.38,relax=0.17
   ).override(other)
"""

WHERE returns clusters, where each cluster contains
multiple solutions.

"""
def where(m,data,slots=where0()):
  out = []
  where1(m,data,slots,0,out)
  return out

def where1(m, data, slots, lvl, out):
  def tooDeep(): return lvl > slots.depthMax
  def tooFew() : return len(data) < slots.minSize
  def show(suffix):
    if slots.verbose:
      print slots.b4*lvl + str(len(data)) + suffix
  if tooDeep() or tooFew():
    show(".")
    out += [data]
  else:
    show("")
    wests,west, easts,east = fastmap(m,data)
    goLeft, goRight = maybePrune(m,slots,lvl,west,east)
    if goLeft:
      where1(m, wests, slots, lvl+1, out)
    if goRight:
      where1(m, easts, slots, lvl+1, out)
"""

Is this useful? Well, in the following experiment, I
clustered 32, 64, 128, 256 individuals using WHERE or
a dumb greedy approach called GAC that (a) finds
everyone's closest neighbor; (b) combines each such
pair into a super-node; (c) then repeats
(recursively) for the super-nodes.

[[etc/img/gacWHEREruntimes.png]]

WHERE is _much_ faster than GAC since it builds
a tree of cluster of height log(N) by, at each
step, making only  O(2N) calls to FastMap.

### Experimental Extensions

Lately I've been experimenting with a system that
prunes as it divides the data. GALE checks for
domination between the poles and ignores data in
halves with a dominated pole. This means that for
_N_ solutions we only ever have to evaluate
_2*log(N)_ of them- which is useful if each
evaluation takes a long time.

The niches found in this way
contain non-dominated poles; i.e. they are
approximations to the Pareto frontier.
Preliminary results show that this is a useful
approach but you should treat those results with a
grain of salt.

In any case, this code supports that pruning as an
optional extra (and is enabled using the
_slots.pruning_ flag). In summary, this code says if
the scores for the poles are more different that
_slots.wriggle_ and one pole has a better score than
the other, then ignore the other pole.

"""
def maybePrune(m,slots,lvl,west,east):
  "Usually, go left then right, unless dominated."
  goLeft, goRight = True,True # default
  if  slots.prune and lvl >= slots.depthMin:
    sw = scores(m, west)
    se = scores(m, east)
    if abs(sw - se) > slots.wriggle: # big enough to consider
      if se > sw: goLeft   = False   # no left
      if sw > se: goRight  = False   # no right
  return goLeft, goRight
"""

Note that I do not allow pruning until we have
descended at least _slots.depthMin_ into the tree.

Support Code
------------

### Dull, low-level stuff

"""
import sys,math,random
sys.dont_write_bytecode = True

def go(f):
  "A decorator that runs code at load time."
  print "\n# ---|", f.__name__,"|-----------------"
  if f.__doc__: print "#", f.__doc__
  f()

# random stuff
by   = lambda x: random.uniform(0,x)
seed = random.seed
any  = random.choice

# pretty-prints for list
def gs(lst) : return [g(x) for x in lst]
def g(x)    : return float('%g' % x)
"""

### More interesting, low-level stuff

"""
def timing(f,repeats=10):
  "How long does 'f' take to run?"
  import time
  time1 = time.clock()
  for _ in range(repeats):
    f()
  return (time.clock() - time1)*1.0/repeats

def showd(d):
  "Pretty print a dictionary."
  def one(k,v):
    if isinstance(v,list):
      v = gs(v)
    if isinstance(v,float):
      return ":%s %g" % (k,v)
    return ":%s %s" % (k,v)
  return ' '.join([one(k,v) for k,v in
                    sorted(d.items())
                     if not "_" in k])

class Num:
  "An Accumulator for numbers"
  def __init__(i): i.n = i.m2 = i.mu = 0.0
  def s(i)       : return (i.m2/(i.n - 1))**0.5
  def __add__(i,x):
    i.n   += 1
    delta  = x - i.mu
    i.mu  += delta*1.0/i.n
    i.m2  += delta*(x - i.mu)
"""

### Model-specific Stuff

WHERE talks to models via the the following model-specific functions.
Here, we must invent some made-up model that builds
individuals with 4 decisions and 3 objectives.
In practice, you would **start** here to build hooks from WHERE into your model
(which is the **m** passed in to these functions).

"""
def decisions(m) : return [0,1,2,3,4]
def objectives(m): return [0,1,2,3]
def lo(m,x)      : return 0.0
def hi(m,x)      : return  1.0
def w(m,o)       : return 1 # min,max is -1,1
def score(m, individual):
  d, o = individual.dec, individual.obj
  o[0] = d[0] * d[1]
  o[1] = d[2] ** d[3]
  o[2] = 2.0*d[3]*d[4] / (d[3] + d[4])
  o[3] =  d[2]/(1 + math.e**(-1*d[2]))
  individual.changed = True
"""

The call to
### Model-general stuff

Using the model-specific stuff, WHERE defines some
useful general functions.

"""
def some(m,x) :
  "with variable x of model m, pick one value at random"
  return lo(m,x) + by(hi(m,x) - lo(m,x))

def candidate(m):
  "Return an unscored individual."
  return Slots(changed = True,
            scores=None,
            obj = [None] * len(objectives(m)),
            dec = [some(m,d)
                   for d in decisions(m)])

def scores(m,t):
  "Score an individual."
  if t.changed:
    score(m,t)
    new, n = 0, 0
    for o in objectives(m):
      x   = t.obj[o]
      n  += 1
      tmp = norm(m,o,x)**2
    if w(m,o) < 0:
      tmp = 1 - tmp
    new += tmp
    t.scores = (new**0.5)*1.0 / (n**0.5)
    t.changed = False
  return t.scores
"""

### Demo stuff

To run these at load time, add _@go_ (uncommented) on the line before.

Checks that we can find lost and distant things:

"""
@go
def _distances():
  def closest(m,i,all):
    return furthest(m,i,all,10**32,lambda x,y: x < y)
  random.seed(1)
  m   = "any"
  pop = [candidate(m) for _ in range(4)]
  for i in pop:
    j = closest(m,i,pop)
    k = furthest(m,i,pop)
    print "\n",\
          gs(i.dec), g(scores(m,i)),"\n",\
          gs(j.dec),"closest ", g(dist(m,i,j)),"\n",\
          gs(k.dec),"furthest", g(dist(m,i,k))
    print i
"""

A standard call to WHERE, pruning disabled:

"""
@go
def _where():
  random.seed(1)
  m, max, pop, kept = "model",100, [], Num()
  for _ in range(max):
    one = candidate(m)
    kept + scores(m,one)
    pop += [one]
  slots = where0(verbose = True,
               minSize = max**0.5,
               prune   = False,
               wriggle = 0.3*kept.s())
  n=0
  for leaf in where(m, pop, slots):
    n += len(leaf)
  print n,slots
"""

Compares WHERE to GAC:

"""
@go
def _whereTiming():
  def allPairs(data):
    n = 8.0/3*(len(data)**2 - 1) #numevals WHERE vs GAC
    for _ in range(int(n+0.5)):
      d1 = any(data)
      d2 = any(data)
      dist("M",d1,d2)
  random.seed(1)
  for max in [32,64,128,256]:
    m, pop, kept = "model",[], Num()
    for _ in range(max):
      one = candidate(m)
      kept + scores(m,one)
      pop += [one]
    slots = where0(verbose = False,
                minSize = 2, # emulate GAC
                depthMax=1000000,
                prune   = False,
                wriggle = 0.3*kept.s())
    t1 =  timing(lambda : where(m, pop, slots),10)
    t2 =  timing(lambda : allPairs(pop),10)
    print max,t1,t2, int(100*t2/t1)


text:
<?php

namespace Image\Fx;

use Image\Plugin\PluginAbstract;

abstract class FxBase extends PluginAbstract
{
    public static function factory($name, $args)
    {
        $className = __NAMESPACE__.'\\'.ucfirst(strtolower($name));

        if (class_exists($className)) {
            $obj = new \ReflectionClass($className);

            return $obj->newInstanceArgs($args);
        }

        return false;
    }
}


text:
<!DOCTYPE html>

		<meta charset="utf-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<title>News - Summary Extraction</title>
		<link rel="stylesheet" href="css/bootstrap.css">
		<link rel="stylesheet" href="css/news.css">

		How to Start a Startup

		startupclass.samaltman.com

			CS183B is a class we're teaching at Stanford. It's designed to be a sort of one-class business course for people who want to start startups.

		Requests for Startups

		www.ycombinator.com

			You shouldn't start a company just because it's on this list. 1. It's mostly here to help stimulate you to think about ideas.

		Peter Thiel, technology entrepreneur and investor. AMA • /r/IAmA

		www.reddit.com

			**My short bio:** Hi, I'm Peter Thiel, co-founder of PayPal and Palantir, first investor in Facebook, venture capitalist at Founders Fund, and...

		Twitter

		twitter.com

		Occupational Hazards of Working on Wall Street

		www.bloombergview.com

			Michael Lewis asks the big question about the army of Ivy League graduates, with seemingly endless career options, who wind up in finance: What ...

		Troy Hunt: Everything you need to know about the Shellshock Bash bug

		www.troyhunt.com

			Observations, musings and conjecture about the world of software and technology

		Brave New Phone Call

		medium.com

			Ray Ozzie's new app Talko hopes to give people their voices back

		Keynote by John Carmack at Oculus Connect 2014

		www.youtube.com

			Starts at the 2:00 mark

		Entrepreneurs anonymous

		www.economist.com

			SEVEN years ago Joe Jones (not his real name) left his job with a big NASDAQ-listed company to strike out on his own. He was sick of corporate life ...

		After Surgery, Surprise $117,000 Medical Bill From Doctor He Didn't Know

		www.nytimes.com

			In a growing practice, medical assistants, consultants and other hospital staffers, often called in without patients' knowledge, are charging hefty ...

		How the Ray Rice scandal unfolded

		espn.go.com

			Outside the Lines: A pattern of misinformation and misdirection was employed by the Baltimore Ravens and the NFL after Ray Rice hit his wife.

		A Long, Ugly Year of Depression That's Finally Fading - Rand's Blog

		moz.com

			Yesterday morning I woke up early to speak at the Business of Software conference in Boston. It was my first time there, and it's an exceptional ...

		Marc Andreessen Sounds Warning on Start-Ups Burning Cash

		dealbook.nytimes.com

			The prominent venture capitalist took to Twitter on Thursday to warn against excessive spending by start-ups that have attracted capital from ...

		oss-sec: Re: CVE-2014-6271: remote code execution through bash

		seclists.org

			oss-sec mailing list archives

		Out in the Open: The Site That Teaches You to Code Well Enough to Get a ...

		www.wired.com

			Wanna be a programmer? That shouldn't be too hard. You can sign-up for an iterative online tutorial at a site like Codecademy or Treehouse. You can ...

		Billionaire must let public access Martins Beach, judge rules

		www.sfgate.com

			"It's a fabulous victory for the people of California because now their coast is safe," said Joe Cotchett, lead attorney for the Surfrider ...

		Lecture 1 - How to Start a Startup

		startupclass.samaltman.com

			Discuss this lecture!

		Home - HeForShe

		www.heforshe.org

			A Solidarity Movement for Gender Equality

		Neural-Network

		nxxcxx.github.io

		An Article on Shonda Rhimes Rightly Causes a Furor - NYTimes.com

		publiceditor.blogs.nytimes.com

			The article on the television producer Shonda Rhimes hadn't yet appeared in Sunday's paper, but the virtual world was ablaze in protest over it on ...

		Ways to think about watches

		ben-evans.com

			Standing in Cupertino last week, holding an Apple watch in my hand, I was reminded very much of the original iPad launch. Here is an idea for a new ...

		Tech Cocktail Celebrate Conference 2014

		celebrate.tech.co

			Celebrate is a national tech conference and startup competition offering inspiring speakers, parties, llamas, more held in downtown Las Vegas October ...

		Zenefits' Leader Is Rattling an Industry, So Why Is He Stressed Out? - ...

		www.nytimes.com

			Parker Conrad's start-up, Zenefits, is thought to be one of the fastest-growing companies in recent Silicon Valley history, and his investors and ...

		scottsievert/xkcd-688

		github.com

			Contribute to xkcd-688 development by creating an account on GitHub.

		How Gary Hart's Downfall Forever Changed American Politics - NYTimes.com

		www.nytimes.com

			On a scalding July day five years ago, I found myself hiking in Red Rocks Park, just outside Denver, with Gary Hart. The copper cliffs were ...

		Burn Baby Burn – AVC

		avc.com

			Andy sent me a WSJ piece with Bill Gurley yesterday. I don't like to link to paid content so here's a good Business Insider summary of the article ...

		Daring Fireball: Apple Watch: Initial Thoughts and Observations

		daringfireball.net

			By John Gruber

		Tesla CEO Musk Sees Fully Autonomous Car Ready in Five or Six Years

		online.wsj.com

			Tesla Motors's Chief Executive Elon Musk said the technology for a fully autonomous car will be ready in five or six years, and the result will be a ...

		Anger Over Songs Of Innocence – Marco.org

		www.marco.org

			September 16, 2014 • ∞ http://www.marco.org/2014/09/16/this-u2-album-really-does-suck

		Applying to YC

		blog.samaltman.com

			One of the most common misconceptions startups have about applying to Y Combinator is thinking that they are too early or too late. We have funded ...


text:
Simple utility to print parameters from Amazon Systems Manager (ssm) Parameter Store as environment variables. This is useful for injecting secure secrets into the environment of a docker container process.

### Usage
Create secret parameters on AWS Parameter Store for your application using [hierarchies](http://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-paramstore-working.html#sysman-paramstore-su-organize):
```
> aws ssm put-parameter --name /userservice/SECRET_1 --value "123456" --type SecureString
> aws ssm put-parameter --name /accountservice/secret_2 --value "abcdef" --type SecureString
> aws ssm put-parameter --name /accountservice/secret_3 --value "foobarbaz" --type SecureString
> aws ssm put-parameter --name /database/production/password --value "productionpass" --type SecureString
> aws ssm put-parameter --name /database/staging/password --value "stagingpass" --type SecureString
```
Add tags to categorize parameters in various ways:
```
> aws ssm add-tags-to-resource --resource-type Parameter --resource-id /userservice/SECRET_1 --tags Key=userservice,Value=true Key=production,Value=true
> aws ssm add-tags-to-resource --resource-type Parameter --resource-id /accountservice/secret_2 --tags Key=accountservice,Value=true Key=production,Value=true
> aws ssm add-tags-to-resource --resource-type Parameter --resource-id /accountservice/secret_3 --tags Key=accountservice,Value=true Key=staging,Value=true
> aws ssm add-tags-to-resource --resource-type Parameter --resource-id /database/production/password --tags Key=userservice,Value=true Key=accountservice,Value=true Key=production,Value=true
> aws ssm add-tags-to-resource --resource-type Parameter --resource-id /database/staging/password --tags Key=userservice,Value=true Key=accountservice,Value=true Key=staging,Value=true
```

#### Retrieve and print parameters with `aws-ssm-env`:

*Notice that parameter names are automatically capitalized.*
```
# filter by tag: print 'userservice' parameters for 'production'
> AWS_REGION=<aws-region> aws-ssm-env --tags=userservice,production
SECRET_1=123456
PASSWORD=productionpass

# filter by tag: print 'accountservice' parameters for 'staging'
> AWS_REGION=<aws-region> aws-ssm-env --tags=accountservice,staging
SECRET_3=foobarbaz
PASSWORD=stagingpass

# filter by path: print all database parameters
> AWS_REGION=<aws-region> aws-ssm-env --paths=/database
PASSWORD=productionpass
PASSWORD=stagingpass

# filter by path and tag: print database parameters for 'production'
> AWS_REGION=<aws-region> aws-ssm-env --paths=/database --tags=production
PASSWORD=productionpass
```

**WARNING: Using `'/'` as a path (e.g. `--paths=/`) will recursively retrieve EVERY single parameter configured in Parameter Store.  This will increase the runtime of this script and could result in hitting SSM rate limits. Use of `'/'` as a path is highly discouraged.**

Use `export` with `aws-ssm-env` to inject secrets from Parameter Store into the environment:
```
> export $(AWS_REGION=<aws-region> aws-ssm-env --tags=userservice,production)
> env
...
...
SECRET_1=123456
PASSWORD=productionpass
```

#### Setting parameters into environment from application code
If you have a need to set SSM parameters as environment variables directly from application code:
```
// retrieve database parameters for production and set each as env variables
fetch.MustSetEnv([]string{"/database"}, []string{"production"}, true)
```

### Installation
go get:
```
> go get github.com/jamietsao/aws-ssm-env
```
Or download [binary](https://github.com/jamietsao/aws-ssm-env/releases/latest):
```
> wget -O aws-ssm-env.zip https://github.com/jamietsao/aws-ssm-env/releases/download/v2.0.0/aws-ssm-env-v2.0.0-linux-amd64.zip
> unzip aws-ssm-env.zip
> chmod 755 aws-ssm-env
```

### Author
Jamie Tsao

### License
MIT


text:
package org.apache.rya.indexing.accumulo.entity;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.accumulo.core.client.AccumuloException;
import org.apache.accumulo.core.client.AccumuloSecurityException;
import org.apache.accumulo.core.client.BatchWriter;
import org.apache.accumulo.core.client.BatchWriterConfig;
import org.apache.accumulo.core.client.Connector;
import org.apache.accumulo.core.client.TableExistsException;
import org.apache.accumulo.core.client.TableNotFoundException;
import org.apache.accumulo.core.client.mock.MockInstance;
import org.apache.accumulo.core.data.Mutation;
import org.apache.accumulo.core.data.Value;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.Text;
import org.apache.rya.accumulo.AccumuloRdfConfiguration;
import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
import org.apache.rya.api.layout.TablePrefixLayoutStrategy;
import org.apache.rya.api.persist.RdfEvalStatsDAO;
import org.apache.rya.indexing.accumulo.ConfigUtils;
import org.apache.rya.joinselect.AccumuloSelectivityEvalDAO;
import org.apache.rya.prospector.service.ProspectorServiceEvalStatsDAO;
import org.eclipse.rdf4j.query.MalformedQueryException;
import org.eclipse.rdf4j.query.QueryEvaluationException;
import org.eclipse.rdf4j.query.TupleQueryResultHandlerException;
import org.eclipse.rdf4j.query.algebra.QueryModelNode;
import org.eclipse.rdf4j.query.algebra.TupleExpr;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.FilterOptimizer;
import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor;
import org.eclipse.rdf4j.query.parser.ParsedQuery;
import org.eclipse.rdf4j.query.parser.sparql.SPARQLParser;
import org.eclipse.rdf4j.repository.RepositoryException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

public class EntityOptimizerTest {

    private static final String DELIM = "\u0000";
    private final byte[] EMPTY_BYTE = new byte[0];
    private final Value EMPTY_VAL = new Value(EMPTY_BYTE);

    private String q1 = ""//
        + "SELECT ?h  " //
        + "{" //
        + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> <uri:dog> ."//
        + "  ?h <uri:barksAt> <uri:cat> ."//
        + "  ?h <uri:peesOn> <uri:hydrant> . "//
        + "}";//

    private String q2 = ""//
        + "SELECT ?h ?m" //
        + "{" //
        + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> <uri:dog> ."//
        + "  ?h <uri:barksAt> <uri:cat> ."//
        + "  ?h <uri:peesOn> <uri:hydrant> . "//
        + "  ?m <uri:eats>  <uri:chickens>. " //
        + "  ?m <uri:scratches> <uri:ears>. " //
        + "}";//

    private String Q2 = ""//
        + "SELECT ?h ?l ?m" //
        + "{" //
        + "  ?h <uri:peesOn> <uri:hydrant> . "//
        + "  ?h <uri:barksAt> <uri:cat> ."//
        + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> <uri:dog> ."//
        + "  ?m <uri:eats>  <uri:chickens>. " //
        + "  ?m <uri:scratches> <uri:ears>. " //
        + "}";//

    private String q3 = ""//
        + "SELECT ?h ?l ?m" //
        + "{" //
        + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> <uri:dog> ."//
        + "  ?h <uri:barksAt> <uri:cat> ."//
        + "  ?h <uri:peesOn> <uri:hydrant> . "//
        + "  {?m <uri:eats>  <uri:chickens>} OPTIONAL {?m <uri:scratches> <uri:ears>}. " //
        + "  {?m <uri:eats>  <uri:kibble>. ?m <uri:watches> <uri:television>.} UNION {?m <uri:rollsIn> <uri:mud>}. " //
        + "  ?l <uri:runsIn> <uri:field> ."//
        + "  ?l <uri:smells> <uri:butt> ."//
        + "  ?l <uri:eats> <uri:sticks> ."//
        + "}";//

    private String Q4 = ""//
        + "SELECT ?h ?l ?m" //
        + "{" //
        + "  ?h <uri:barksAt> <uri:cat> ."//
        + "  ?m <uri:scratches> <uri:ears>. " //
        + "  ?m <uri:eats>  <uri:chickens>. " //
        + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> <uri:dog> ."//
        + "  ?h <uri:peesOn> <uri:hydrant> . "//
        + "}";//

    private String q5 = ""//
            + "SELECT ?h ?m" //
            + "{" //
            + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> <uri:dog> ."//
            + "  ?h <uri:barksAt> <uri:cat> ."//
            + "  ?h <uri:peesOn> ?m . "//
            + "  ?m <uri:eats>  <uri:chickens>. " //
            + "  ?m <uri:scratches> <uri:ears>. " //
            + "}";//

    private String q6 = ""//
            + "SELECT ?h ?i ?l ?m" //
            + "{" //
            + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> <uri:dog> ."//
            + "  ?h <uri:barksAt> <uri:cat> ."//
            + "  ?h <uri:peesOn> <uri:hydrant> . "//
            + "  {?m <uri:eats>  <uri:chickens>} OPTIONAL {?m <uri:scratches> <uri:ears>}. " //
            + "  {?m <uri:eats> <uri:kibble>. ?m <uri:watches> ?i. ?i <uri:runsIn> <uri:field> .} " //
            + "  UNION {?m <uri:rollsIn> <uri:mud>. ?l <uri:smells> ?m . ?l <uri:eats> <uri:sticks> . }. " //
            + "}";//

    private String q7 = ""//
            + "SELECT ?h ?m" //
            + "{" //
            + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> <uri:chickens> ."//
            + "  ?h <uri:barksAt> <uri:chickens> ."//
            + "  ?h <uri:peesOn> ?m . "//
            + "  ?m <uri:eats>  <uri:chickens>. " //
            + "  ?m <uri:scratches> <uri:ears>. " //
            + "}";//

    private String q8 = ""//
            + "SELECT ?h ?m" //
            + "{" //
            + "  Filter(?h = \"Diego\") " //
            + "  Filter(?m = \"Rosie\") " //
            + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> <uri:chickens> ."//
            + "  ?h <uri:barksAt> <uri:chickens> ."//
            + "  ?h <uri:peesOn> ?m . "//
            + "  ?m <uri:eats>  <uri:chickens>. " //
            + "  ?m <uri:scratches> <uri:ears>. " //
            + "}";//

    private String q9 = ""//
            + "SELECT ?h ?i ?l ?m" //
            + "{" //
            + "  Filter(?h = \"Diego\") " //
            + "  Filter(?m = \"Rosie\") " //
            + "  ?h <http://www.w3.org/2000/01/rdf-schema#label> <uri:dog> ."//
            + "  ?h <uri:barksAt> <uri:cat> ."//
            + "  ?h <uri:peesOn> <uri:hydrant> . "//
            + "  {?m <uri:eats>  <uri:chickens>} OPTIONAL {?m <uri:scratches> <uri:ears>}. " //
            + "  {   Filter(?i = \"Bobo\").  ?m <uri:eats> <uri:kibble>. ?m <uri:watches> ?i. ?i <uri:runsIn> <uri:field> .} " //
            + "  UNION {?m <uri:rollsIn> <uri:mud>. ?l <uri:smells> ?m . ?l <uri:eats> <uri:sticks> . }. " //
            + "}";//

    private Connector accCon;
    AccumuloRdfConfiguration conf;
    BatchWriterConfig config;
    RdfEvalStatsDAO<RdfCloudTripleStoreConfiguration> res;

    @Before
    public void init() throws RepositoryException, TupleQueryResultHandlerException, QueryEvaluationException,
            MalformedQueryException, AccumuloException, AccumuloSecurityException, TableExistsException {

        accCon = new MockInstance("instance").getConnector("root", "".getBytes());

        config = new BatchWriterConfig();
        config.setMaxMemory(1000);
        config.setMaxLatency(1000, TimeUnit.SECONDS);
        config.setMaxWriteThreads(10);

        if (accCon.tableOperations().exists("rya_prospects")) {
            try {
                accCon.tableOperations().delete("rya_prospects");
            } catch (TableNotFoundException e) {
                e.printStackTrace();
            }
        }
        if (accCon.tableOperations().exists("rya_selectivity")) {
            try {
                accCon.tableOperations().delete("rya_selectivity");
            } catch (TableNotFoundException e) {
                e.printStackTrace();
            }
        }

        accCon.tableOperations().create("rya_prospects");
        accCon.tableOperations().create("rya_selectivity");

        Configuration con = new Configuration();
        con.set(ConfigUtils.CLOUDBASE_AUTHS, "U");
        con.set(ConfigUtils.CLOUDBASE_INSTANCE, "instance");
        con.set(ConfigUtils.CLOUDBASE_USER, "root");
        con.set(ConfigUtils.CLOUDBASE_PASSWORD, "");
        conf = new AccumuloRdfConfiguration(con);
        TablePrefixLayoutStrategy tps = new TablePrefixLayoutStrategy("rya_");
        conf.setTableLayoutStrategy(tps);
        conf.set(ConfigUtils.USE_MOCK_INSTANCE, "true");

        res = new ProspectorServiceEvalStatsDAO(accCon, conf);

    }

 @Test
    public void testOptimizeQ1SamePriority() throws Exception {

      AccumuloSelectivityEvalDAO accc = new AccumuloSelectivityEvalDAO();
      accc.setConf(conf);
      accc.setConnector(accCon);
      accc.setRdfEvalDAO(res);
      accc.init();

      BatchWriter bw1 = accCon.createBatchWriter("rya_prospects", config);
      BatchWriter bw2 = accCon.createBatchWriter("rya_selectivity", config);

      String s1 = "predicateobject" + DELIM + "http://www.w3.org/2000/01/rdf-schema#label" + DELIM + "uri:dog";
      String s2 = "predicateobject" + DELIM + "uri:barksAt" + DELIM + "uri:cat";
      String s3 = "predicateobject" + DELIM + "uri:peesOn" + DELIM + "uri:hydrant";
      List<Mutation> mList = new ArrayList<Mutation>();
      List<Mutation> mList2 = new ArrayList<Mutation>();
      List<String> sList = Arrays.asList("subjectobject", "subjectpredicate", "subjectsubject");
      Mutation m1, m2, m3, m4;

      m1 = new Mutation(s1 + DELIM + "1");
      m1.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m2 = new Mutation(s2 + DELIM + "1");
      m2.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m3 = new Mutation(s3 + DELIM + "1");
      m3.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      mList.add(m1);
      mList.add(m2);
      mList.add(m3);

      bw1.addMutations(mList);
      bw1.close();

      m1 = new Mutation(s1);
      m2 = new Mutation(s2);
      m3 = new Mutation(s3);
      m4 = new Mutation(new Text("subjectpredicateobject" + DELIM + "FullTableCardinality"));
      m4.put(new Text("FullTableCardinality"), new Text("100"), EMPTY_VAL);

      for (String s : sList) {

        m1.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m2.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m3.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);

      }
      mList2.add(m1);
      mList2.add(m2);
      mList2.add(m3);
      mList2.add(m4);
      bw2.addMutations(mList2);
      bw2.close();

      TupleExpr te = getTupleExpr(q1);

      EntityOptimizer cco = new EntityOptimizer(accc);
      System.out.println("Originial query is " + te);
      cco.optimize(te, null, null);

      EntityCentricVisitor ccv = new EntityCentricVisitor();
      te.visit(ccv);

      Assert.assertEquals(1, ccv.getCcNodes().size());

      System.out.println(te);

    }

 @Test
    public void testOptimizeQ2SamePriority() throws Exception {

      AccumuloSelectivityEvalDAO accc = new AccumuloSelectivityEvalDAO();
      accc.setConf(conf);
      accc.setConnector(accCon);
      accc.setRdfEvalDAO(res);
      accc.init();

      BatchWriter bw1 = accCon.createBatchWriter("rya_prospects", config);
      BatchWriter bw2 = accCon.createBatchWriter("rya_selectivity", config);

      String s1 = "predicateobject" + DELIM + "http://www.w3.org/2000/01/rdf-schema#label" + DELIM + "uri:dog";
      String s2 = "predicateobject" + DELIM + "uri:barksAt" + DELIM + "uri:cat";
      String s3 = "predicateobject" + DELIM + "uri:peesOn" + DELIM + "uri:hydrant";
      String s5 = "predicateobject" + DELIM + "uri:scratches" + DELIM + "uri:ears";
      String s4 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:chickens";
      List<Mutation> mList = new ArrayList<Mutation>();
      List<Mutation> mList2 = new ArrayList<Mutation>();
      List<String> sList = Arrays.asList("subjectobject", "subjectpredicate", "subjectsubject");
      Mutation m1, m2, m3, m4, m5, m6;

      m1 = new Mutation(s1 + DELIM + "1");
      m1.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m2 = new Mutation(s2 + DELIM + "1");
      m2.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m3 = new Mutation(s3 + DELIM + "1");
      m3.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m4 = new Mutation(s4 + DELIM + "1");
      m4.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m5 = new Mutation(s5 + DELIM + "1");
      m5.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      mList.add(m1);
      mList.add(m2);
      mList.add(m3);
      mList.add(m4);
      mList.add(m5);

      bw1.addMutations(mList);
      bw1.close();

//      Scanner scan = conn.createScanner("rya_prospects", new Authorizations());
//      scan.setRange(new Range());
//
//      for (Map.Entry<Key,Value> entry : scan) {
//        System.out.println("Key row string is " + entry.getKey().getRow().toString());
//        System.out.println("Key is " + entry.getKey());
//        System.out.println("Value is " + (new String(entry.getValue().get())));
//      }

      m1 = new Mutation(s1);
      m2 = new Mutation(s2);
      m3 = new Mutation(s3);
      m4 = new Mutation(s4);
      m5 = new Mutation(s5);
      m6 = new Mutation(new Text("subjectpredicateobject" + DELIM + "FullTableCardinality"));
      m6.put(new Text("FullTableCardinality"), new Text("100"), EMPTY_VAL);

      for (String s : sList) {

        m1.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m2.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m3.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m4.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m5.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);

      }
      mList2.add(m1);
      mList2.add(m2);
      mList2.add(m3);
      mList2.add(m4);
      mList2.add(m5);
      mList2.add(m6);
      bw2.addMutations(mList2);
      bw2.close();

      TupleExpr te = getTupleExpr(q2);

      EntityOptimizer cco = new EntityOptimizer(accc);
      System.out.println("Originial query is " + te);
      cco.optimize(te, null, null);

      EntityCentricVisitor ccv = new EntityCentricVisitor();
      te.visit(ccv);

      Assert.assertEquals(2, ccv.getCcNodes().size());

      System.out.println(te);

    }

 @Test
    public void testOptimizeQ3SamePriority() throws Exception {

      AccumuloSelectivityEvalDAO accc = new AccumuloSelectivityEvalDAO();
      accc.setConf(conf);
      accc.setConnector(accCon);
      accc.setRdfEvalDAO(res);
      accc.init();

      BatchWriter bw1 = accCon.createBatchWriter("rya_prospects", config);
      BatchWriter bw2 = accCon.createBatchWriter("rya_selectivity", config);

      String s1 = "predicateobject" + DELIM + "http://www.w3.org/2000/01/rdf-schema#label" + DELIM + "uri:dog";
      String s2 = "predicateobject" + DELIM + "uri:barksAt" + DELIM + "uri:cat";
      String s3 = "predicateobject" + DELIM + "uri:peesOn" + DELIM + "uri:hydrant";
      String s5 = "predicateobject" + DELIM + "uri:scratches" + DELIM + "uri:ears";
      String s4 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:chickens";
      String s6 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:kibble";
      String s7 = "predicateobject" + DELIM + "uri:rollsIn" + DELIM + "uri:mud";
      String s8 = "predicateobject" + DELIM + "uri:runsIn" + DELIM + "uri:field";
      String s9 = "predicateobject" + DELIM + "uri:smells" + DELIM + "uri:butt";
      String s10 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:sticks";
      String s11 = "predicateobject" + DELIM + "uri:watches" + DELIM + "uri:television";

      List<Mutation> mList = new ArrayList<Mutation>();
      List<Mutation> mList2 = new ArrayList<Mutation>();
      List<String> sList = Arrays.asList("subjectobject", "subjectpredicate", "subjectsubject");
      Mutation m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12;

      m1 = new Mutation(s1 + DELIM + "1");
      m1.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m2 = new Mutation(s2 + DELIM + "1");
      m2.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m3 = new Mutation(s3 + DELIM + "1");
      m3.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m4 = new Mutation(s4 + DELIM + "1");
      m4.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m5 = new Mutation(s5 + DELIM + "1");
      m5.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m6 = new Mutation(s6 + DELIM + "1");
      m6.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m7 = new Mutation(s7 + DELIM + "1");
      m7.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m8 = new Mutation(s8 + DELIM + "1");
      m8.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m9 = new Mutation(s9 + DELIM + "1");
      m9.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m10 = new Mutation(s10 + DELIM + "1");
      m10.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m11 = new Mutation(s11 + DELIM + "1");
      m11.put(new Text("count"), new Text(""), new Value("1".getBytes()));

      mList.add(m1);
      mList.add(m2);
      mList.add(m3);
      mList.add(m4);
      mList.add(m5);
      mList.add(m6);
      mList.add(m7);
      mList.add(m8);
      mList.add(m9);
      mList.add(m10);
      mList.add(m11);

      bw1.addMutations(mList);
      bw1.close();

      m1 = new Mutation(s1);
      m2 = new Mutation(s2);
      m3 = new Mutation(s3);
      m4 = new Mutation(s4);
      m5 = new Mutation(s5);
      m6 = new Mutation(s6);
      m7 = new Mutation(s7);
      m8 = new Mutation(s8);
      m9 = new Mutation(s9);
      m10 = new Mutation(s10);
      m11 = new Mutation(s11);
      m12 = new Mutation(new Text("subjectpredicateobject" + DELIM + "FullTableCardinality"));
      m12.put(new Text("FullTableCardinality"), new Text("100"), EMPTY_VAL);

      for (String s : sList) {

        m1.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m2.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m3.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m4.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m5.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m6.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m7.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m8.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m9.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m10.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m11.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);

      }
      mList2.add(m1);
      mList2.add(m2);
      mList2.add(m3);
      mList2.add(m4);
      mList2.add(m5);
      mList2.add(m6);
      mList2.add(m7);
      mList2.add(m8);
      mList2.add(m9);
      mList2.add(m10);
      mList2.add(m11);
      mList2.add(m12);
      bw2.addMutations(mList2);
      bw2.close();

      TupleExpr te = getTupleExpr(q3);

      EntityOptimizer cco = new EntityOptimizer(accc);
      System.out.println("Originial query is " + te);
      cco.optimize(te, null, null);

      EntityCentricVisitor ccv = new EntityCentricVisitor();
      te.visit(ccv);

      Assert.assertEquals(3, ccv.getCcNodes().size());

      System.out.println(te);

    }

 @Test
    public void testOptimizeQ2DiffPriority() throws Exception {

      AccumuloSelectivityEvalDAO accc = new AccumuloSelectivityEvalDAO();
      accc.setConf(conf);
      accc.setConnector(accCon);
      accc.setRdfEvalDAO(res);
      accc.init();

      BatchWriter bw1 = accCon.createBatchWriter("rya_prospects", config);
      BatchWriter bw2 = accCon.createBatchWriter("rya_selectivity", config);

      String s1 = "predicateobject" + DELIM + "http://www.w3.org/2000/01/rdf-schema#label" + DELIM + "uri:dog";
      String s2 = "predicateobject" + DELIM + "uri:barksAt" + DELIM + "uri:cat";
      String s3 = "predicate" + DELIM + "uri:peesOn";
      String s5 = "predicateobject" + DELIM + "uri:scratches" + DELIM + "uri:ears";
      String s4 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:chickens";
      List<Mutation> mList = new ArrayList<Mutation>();
      List<Mutation> mList2 = new ArrayList<Mutation>();
      List<String> sList = Arrays.asList("subjectobject", "subjectpredicate", "subjectsubject", "objectsubject", "objectpredicate", "objectobject");
      Mutation m1, m2, m3, m4, m5, m6;

      m1 = new Mutation(s1 + DELIM + "1");
      m1.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m2 = new Mutation(s2 + DELIM + "1");
      m2.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m3 = new Mutation(s3 + DELIM + "1");
      m3.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m4 = new Mutation(s4 + DELIM + "1");
      m4.put(new Text("count"), new Text(""), new Value("3".getBytes()));
      m5 = new Mutation(s5 + DELIM + "1");
      m5.put(new Text("count"), new Text(""), new Value("3".getBytes()));
      mList.add(m1);
      mList.add(m2);
      mList.add(m3);
      mList.add(m4);
      mList.add(m5);

      bw1.addMutations(mList);
      bw1.close();

      m1 = new Mutation(s1);
      m2 = new Mutation(s2);
      m3 = new Mutation(s3);
      m4 = new Mutation(s4);
      m5 = new Mutation(s5);
      m6 = new Mutation(new Text("subjectpredicateobject" + DELIM + "FullTableCardinality"));
      m6.put(new Text("FullTableCardinality"), new Text("100"), EMPTY_VAL);

      for (String s : sList) {

        m1.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);
        m2.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);
        m3.put(new Text(s), new Text(Integer.toString(3)), EMPTY_VAL);
        m4.put(new Text(s), new Text(Integer.toString(3)), EMPTY_VAL);
        m5.put(new Text(s), new Text(Integer.toString(3)), EMPTY_VAL);

      }
      mList2.add(m1);
      mList2.add(m2);
      mList2.add(m3);
      mList2.add(m4);
      mList2.add(m5);
      mList2.add(m6);
      bw2.addMutations(mList2);
      bw2.close();

      TupleExpr te = getTupleExpr(q5);

      EntityOptimizer cco = new EntityOptimizer(accc);
      System.out.println("Originial query is " + te);
      cco.optimize(te, null, null);

      EntityCentricVisitor ccv = new EntityCentricVisitor();
      te.visit(ccv);

      List<QueryModelNode> nodes = Lists.newArrayList(ccv.getCcNodes());

      Assert.assertEquals(2, nodes.size());

      for(QueryModelNode q: nodes) {

          if(((EntityTupleSet)q).getStarQuery().getNodes().size() == 2) {
              Assert.assertEquals("h", ((EntityTupleSet)q).getStarQuery().getCommonVarName());
          } else if(((EntityTupleSet)q).getStarQuery().getNodes().size() == 3) {
              Assert.assertEquals("m", ((EntityTupleSet)q).getStarQuery().getCommonVarName());
          } else {
              Assert.assertTrue(false);
          }
      }

      System.out.println(te);

    }

 @Test
    public void testOptimizeQ2DiffPriority2() throws Exception {

      AccumuloSelectivityEvalDAO accc = new AccumuloSelectivityEvalDAO();
      accc.setConf(conf);
      accc.setConnector(accCon);
      accc.setRdfEvalDAO(res);
      accc.init();

      BatchWriter bw1 = accCon.createBatchWriter("rya_prospects", config);
      BatchWriter bw2 = accCon.createBatchWriter("rya_selectivity", config);

      String s1 = "predicateobject" + DELIM + "http://www.w3.org/2000/01/rdf-schema#label" + DELIM + "uri:dog";
      String s2 = "predicateobject" + DELIM + "uri:barksAt" + DELIM + "uri:cat";
      String s3 = "predicate" + DELIM + "uri:peesOn";
      String s5 = "predicateobject" + DELIM + "uri:scratches" + DELIM + "uri:ears";
      String s4 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:chickens";
      List<Mutation> mList = new ArrayList<Mutation>();
      List<Mutation> mList2 = new ArrayList<Mutation>();
      List<String> sList = Arrays.asList("subjectobject", "subjectpredicate", "subjectsubject", "objectsubject", "objectpredicate", "objectobject");
      Mutation m1, m2, m3, m4, m5, m6;

      m1 = new Mutation(s1 + DELIM + "1");
      m1.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m2 = new Mutation(s2 + DELIM + "1");
      m2.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m3 = new Mutation(s3 + DELIM + "1");
      m3.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m4 = new Mutation(s4 + DELIM + "1");
      m4.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m5 = new Mutation(s5 + DELIM + "1");
      m5.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      mList.add(m1);
      mList.add(m2);
      mList.add(m3);
      mList.add(m4);
      mList.add(m5);

      bw1.addMutations(mList);
      bw1.close();

      m1 = new Mutation(s1);
      m2 = new Mutation(s2);
      m3 = new Mutation(s3);
      m4 = new Mutation(s4);
      m5 = new Mutation(s5);
      m6 = new Mutation(new Text("subjectpredicateobject" + DELIM + "FullTableCardinality"));
      m6.put(new Text("FullTableCardinality"), new Text("100"), EMPTY_VAL);

      for (String s : sList) {

        m1.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);
        m2.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);
        m3.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);
        m4.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);
        m5.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);

      }
      mList2.add(m1);
      mList2.add(m2);
      mList2.add(m3);
      mList2.add(m4);
      mList2.add(m5);
      mList2.add(m6);
      bw2.addMutations(mList2);
      bw2.close();

      TupleExpr te = getTupleExpr(q5);

      EntityOptimizer cco = new EntityOptimizer(accc);
      System.out.println("Originial query is " + te);
      cco.optimize(te, null, null);

      EntityCentricVisitor ccv = new EntityCentricVisitor();
      te.visit(ccv);

      List<QueryModelNode> nodes = Lists.newArrayList(ccv.getCcNodes());

      Assert.assertEquals(2, nodes.size());

      for(QueryModelNode q: nodes) {

          if(((EntityTupleSet)q).getStarQuery().getNodes().size() == 2) {
              Assert.assertEquals("m", ((EntityTupleSet)q).getStarQuery().getCommonVarName());
          } else if(((EntityTupleSet)q).getStarQuery().getNodes().size() == 3) {
              Assert.assertEquals("h", ((EntityTupleSet)q).getStarQuery().getCommonVarName());
          } else {
              Assert.assertTrue(false);
          }
      }

      System.out.println(te);

    }

 @Test
    public void testOptimizeQ6DiffPriority() throws Exception {

      AccumuloSelectivityEvalDAO accc = new AccumuloSelectivityEvalDAO();
      accc.setConf(conf);
      accc.setConnector(accCon);
      accc.setRdfEvalDAO(res);
      accc.init();

      BatchWriter bw1 = accCon.createBatchWriter("rya_prospects", config);
      BatchWriter bw2 = accCon.createBatchWriter("rya_selectivity", config);

      String s1 = "predicateobject" + DELIM + "http://www.w3.org/2000/01/rdf-schema#label" + DELIM + "uri:dog";
      String s2 = "predicateobject" + DELIM + "uri:barksAt" + DELIM + "uri:cat";
      String s3 = "predicateobject" + DELIM + "uri:peesOn" + DELIM + "uri:hydrant";
      String s5 = "predicateobject" + DELIM + "uri:scratches" + DELIM + "uri:ears";
      String s4 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:chickens";
      String s6 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:kibble";
      String s7 = "predicateobject" + DELIM + "uri:rollsIn" + DELIM + "uri:mud";
      String s8 = "predicateobject" + DELIM + "uri:runsIn" + DELIM + "uri:field";
      String s9 = "predicate" + DELIM + "uri:smells" ;
      String s10 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:sticks";
      String s11 = "predicate" + DELIM + "uri:watches";

      List<Mutation> mList = new ArrayList<Mutation>();
      List<Mutation> mList2 = new ArrayList<Mutation>();
      List<String> sList = Arrays.asList("subjectobject", "subjectpredicate", "subjectsubject","objectsubject", "objectpredicate", "objectobject");
      Mutation m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12;

      m1 = new Mutation(s1 + DELIM + "1");
      m1.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m2 = new Mutation(s2 + DELIM + "1");
      m2.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m3 = new Mutation(s3 + DELIM + "1");
      m3.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m4 = new Mutation(s4 + DELIM + "1");
      m4.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m5 = new Mutation(s5 + DELIM + "1");
      m5.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m6 = new Mutation(s6 + DELIM + "1");
      m6.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m7 = new Mutation(s7 + DELIM + "1");
      m7.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m8 = new Mutation(s8 + DELIM + "1");
      m8.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m9 = new Mutation(s9 + DELIM + "1");
      m9.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m10 = new Mutation(s10 + DELIM + "1");
      m10.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m11 = new Mutation(s11 + DELIM + "1");
      m11.put(new Text("count"), new Text(""), new Value("2".getBytes()));

      mList.add(m1);
      mList.add(m2);
      mList.add(m3);
      mList.add(m4);
      mList.add(m5);
      mList.add(m6);
      mList.add(m7);
      mList.add(m8);
      mList.add(m9);
      mList.add(m10);
      mList.add(m11);

      bw1.addMutations(mList);
      bw1.close();

      m1 = new Mutation(s1);
      m2 = new Mutation(s2);
      m3 = new Mutation(s3);
      m4 = new Mutation(s4);
      m5 = new Mutation(s5);
      m6 = new Mutation(s6);
      m7 = new Mutation(s7);
      m8 = new Mutation(s8);
      m9 = new Mutation(s9);
      m10 = new Mutation(s10);
      m11 = new Mutation(s11);
      m12 = new Mutation(new Text("subjectpredicateobject" + DELIM + "FullTableCardinality"));
      m12.put(new Text("FullTableCardinality"), new Text("100"), EMPTY_VAL);

      for (String s : sList) {

        m1.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m2.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m3.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m4.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m5.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m6.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m7.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);
        m8.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);
        m9.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);
        m10.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m11.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);

      }
      mList2.add(m1);
      mList2.add(m2);
      mList2.add(m3);
      mList2.add(m4);
      mList2.add(m5);
      mList2.add(m6);
      mList2.add(m7);
      mList2.add(m8);
      mList2.add(m9);
      mList2.add(m10);
      mList2.add(m11);
      mList2.add(m12);
      bw2.addMutations(mList2);
      bw2.close();

      TupleExpr te = getTupleExpr(q6);

      EntityOptimizer cco = new EntityOptimizer(accc);
      System.out.println("Originial query is " + te);
      cco.optimize(te, null, null);

      EntityCentricVisitor ccv = new EntityCentricVisitor();
      te.visit(ccv);

      List<QueryModelNode> nodes = Lists.newArrayList(ccv.getCcNodes());

      Assert.assertEquals(3, nodes.size());
      List<String> cVarList = Lists.newArrayList();
      cVarList.add("i");
      cVarList.add("m");

      for(QueryModelNode q: nodes) {

          if(((EntityTupleSet)q).getStarQuery().getNodes().size() == 2) {
              String s = ((EntityTupleSet)q).getStarQuery().getCommonVarName();
              System.out.println("node is " + q  + " and common var is " + s);
              System.out.println("star query is " + ((EntityTupleSet)q).getStarQuery());
              Assert.assertTrue(cVarList.contains(s));
              cVarList.remove(s);
          } else if(((EntityTupleSet)q).getStarQuery().getNodes().size() == 3) {
              Assert.assertEquals("h", ((EntityTupleSet)q).getStarQuery().getCommonVarName());
          } else {
              Assert.assertTrue(false);
          }
      }

      System.out.println(te);

    }

    @Test
    public void testOptimizeConstantPriority() throws Exception {

        AccumuloSelectivityEvalDAO accc = new AccumuloSelectivityEvalDAO();
        accc.setConf(conf);
        accc.setConnector(accCon);
        accc.setRdfEvalDAO(res);
        accc.init();

        BatchWriter bw1 = accCon.createBatchWriter("rya_prospects", config);
        BatchWriter bw2 = accCon.createBatchWriter("rya_selectivity", config);

        String s1 = "predicateobject" + DELIM + "http://www.w3.org/2000/01/rdf-schema#label" + DELIM + "uri:chickens";
        String s2 = "predicateobject" + DELIM + "uri:barksAt" + DELIM + "uri:chickens";
        String s3 = "predicate" + DELIM + "uri:peesOn";
        String s5 = "predicateobject" + DELIM + "uri:scratches" + DELIM + "uri:ears";
        String s4 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:chickens";
        List<Mutation> mList = new ArrayList<Mutation>();
        List<Mutation> mList2 = new ArrayList<Mutation>();
        List<String> sList = Arrays.asList("subjectobject", "subjectpredicate", "subjectsubject", "objectsubject",
                "objectpredicate", "objectobject");
        Mutation m1, m2, m3, m4, m5, m6;

        m1 = new Mutation(s1 + DELIM + "1");
        m1.put(new Text("count"), new Text(""), new Value("2".getBytes()));
        m2 = new Mutation(s2 + DELIM + "1");
        m2.put(new Text("count"), new Text(""), new Value("2".getBytes()));
        m3 = new Mutation(s3 + DELIM + "1");
        m3.put(new Text("count"), new Text(""), new Value("2".getBytes()));
        m4 = new Mutation(s4 + DELIM + "1");
        m4.put(new Text("count"), new Text(""), new Value("2".getBytes()));
        m5 = new Mutation(s5 + DELIM + "1");
        m5.put(new Text("count"), new Text(""), new Value("2".getBytes()));
        mList.add(m1);
        mList.add(m2);
        mList.add(m3);
        mList.add(m4);
        mList.add(m5);

        bw1.addMutations(mList);
        bw1.close();

        m1 = new Mutation(s1);
        m2 = new Mutation(s2);
        m3 = new Mutation(s3);
        m4 = new Mutation(s4);
        m5 = new Mutation(s5);
        m6 = new Mutation(new Text("subjectpredicateobject" + DELIM + "FullTableCardinality"));
        m6.put(new Text("FullTableCardinality"), new Text("100"), EMPTY_VAL);

        for (String s : sList) {

            m1.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
            m2.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
            m3.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
            m4.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
            m5.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);

        }
        mList2.add(m1);
        mList2.add(m2);
        mList2.add(m3);
        mList2.add(m4);
        mList2.add(m5);
        mList2.add(m6);
        bw2.addMutations(mList2);
        bw2.close();

        TupleExpr te = getTupleExpr(q7);

        EntityOptimizer cco = new EntityOptimizer(accc);
        System.out.println("Originial query is " + te);
        cco.optimize(te, null, null);

        EntityCentricVisitor ccv = new EntityCentricVisitor();
        te.visit(ccv);

        List<QueryModelNode> nodes = Lists.newArrayList(ccv.getCcNodes());
        System.out.println("Test 7 nodes are :" + nodes);

        Assert.assertEquals(2, nodes.size());

        for (QueryModelNode q : nodes) {
            final StarQuery starQuery = ((EntityTupleSet) q).getStarQuery();
            if (starQuery.getNodes().size() == 2) {
                Assert.assertEquals("m", starQuery.getCommonVarName());
            } else if (starQuery.getNodes().size() == 3) {
                Assert.assertEquals("uri:chickens", starQuery.getCommonVarValue());
            } else {
                Assert.assertTrue(false);
            }
        }

        System.out.println(te);

    }

    @Test
    public void testOptimizeFilters() throws Exception {

        AccumuloSelectivityEvalDAO accc = new AccumuloSelectivityEvalDAO();
        accc.setConf(conf);
        accc.setConnector(accCon);
        accc.setRdfEvalDAO(res);
        accc.init();

        BatchWriter bw1 = accCon.createBatchWriter("rya_prospects", config);
        BatchWriter bw2 = accCon.createBatchWriter("rya_selectivity", config);

        String s1 = "predicateobject" + DELIM + "http://www.w3.org/2000/01/rdf-schema#label" + DELIM + "uri:chickens";
        String s2 = "predicateobject" + DELIM + "uri:barksAt" + DELIM + "uri:chickens";
        String s3 = "predicate" + DELIM + "uri:peesOn";
        String s5 = "predicateobject" + DELIM + "uri:scratches" + DELIM + "uri:ears";
        String s4 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:chickens";
        List<Mutation> mList = new ArrayList<Mutation>();
        List<Mutation> mList2 = new ArrayList<Mutation>();
        List<String> sList = Arrays.asList("subjectobject", "subjectpredicate", "subjectsubject", "objectsubject",
                "objectpredicate", "objectobject");
        Mutation m1, m2, m3, m4, m5, m6;

        m1 = new Mutation(s1 + DELIM + "1");
        m1.put(new Text("count"), new Text(""), new Value("2".getBytes()));
        m2 = new Mutation(s2 + DELIM + "1");
        m2.put(new Text("count"), new Text(""), new Value("2".getBytes()));
        m3 = new Mutation(s3 + DELIM + "1");
        m3.put(new Text("count"), new Text(""), new Value("2".getBytes()));
        m4 = new Mutation(s4 + DELIM + "1");
        m4.put(new Text("count"), new Text(""), new Value("2".getBytes()));
        m5 = new Mutation(s5 + DELIM + "1");
        m5.put(new Text("count"), new Text(""), new Value("2".getBytes()));
        mList.add(m1);
        mList.add(m2);
        mList.add(m3);
        mList.add(m4);
        mList.add(m5);

        bw1.addMutations(mList);
        bw1.close();

        m1 = new Mutation(s1);
        m2 = new Mutation(s2);
        m3 = new Mutation(s3);
        m4 = new Mutation(s4);
        m5 = new Mutation(s5);
        m6 = new Mutation(new Text("subjectpredicateobject" + DELIM + "FullTableCardinality"));
        m6.put(new Text("FullTableCardinality"), new Text("100"), EMPTY_VAL);

        for (String s : sList) {

            m1.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
            m2.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
            m3.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
            m4.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
            m5.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);

        }
        mList2.add(m1);
        mList2.add(m2);
        mList2.add(m3);
        mList2.add(m4);
        mList2.add(m5);
        mList2.add(m6);
        bw2.addMutations(mList2);
        bw2.close();

        TupleExpr te = getTupleExpr(q8);
        (new FilterOptimizer()).optimize(te,null,null);

        EntityOptimizer cco = new EntityOptimizer(accc);
        System.out.println("Originial query is " + te);
        cco.optimize(te, null, null);

        EntityCentricVisitor ccv = new EntityCentricVisitor();
        te.visit(ccv);

        List<QueryModelNode> nodes = Lists.newArrayList(ccv.getCcNodes());
        System.out.println("Test 8 nodes are :" + nodes);

        Assert.assertEquals(2, nodes.size());

        for (QueryModelNode q : nodes) {
            final StarQuery starQuery = ((EntityTupleSet) q).getStarQuery();
            if (starQuery.getNodes().size() == 2) {
                Assert.assertEquals("m", starQuery.getCommonVarName());
            } else if (starQuery.getNodes().size() == 3) {
                Assert.assertEquals("uri:chickens", starQuery.getCommonVarValue());
            } else {
                Assert.assertTrue(false);
            }
        }

        System.out.println(te);

    }

    @Test
    public void testOptimizeFilter2() throws Exception {

      AccumuloSelectivityEvalDAO accc = new AccumuloSelectivityEvalDAO();
      accc.setConf(conf);
      accc.setConnector(accCon);
      accc.setRdfEvalDAO(res);
      accc.init();

      BatchWriter bw1 = accCon.createBatchWriter("rya_prospects", config);
      BatchWriter bw2 = accCon.createBatchWriter("rya_selectivity", config);

      String s1 = "predicateobject" + DELIM + "http://www.w3.org/2000/01/rdf-schema#label" + DELIM + "uri:dog";
      String s2 = "predicateobject" + DELIM + "uri:barksAt" + DELIM + "uri:cat";
      String s3 = "predicateobject" + DELIM + "uri:peesOn" + DELIM + "uri:hydrant";
      String s5 = "predicateobject" + DELIM + "uri:scratches" + DELIM + "uri:ears";
      String s4 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:chickens";
      String s6 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:kibble";
      String s7 = "predicateobject" + DELIM + "uri:rollsIn" + DELIM + "uri:mud";
      String s8 = "predicateobject" + DELIM + "uri:runsIn" + DELIM + "uri:field";
      String s9 = "predicate" + DELIM + "uri:smells" ;
      String s10 = "predicateobject" + DELIM + "uri:eats" + DELIM + "uri:sticks";
      String s11 = "predicate" + DELIM + "uri:watches";

      List<Mutation> mList = new ArrayList<Mutation>();
      List<Mutation> mList2 = new ArrayList<Mutation>();
      List<String> sList = Arrays.asList("subjectobject", "subjectpredicate", "subjectsubject","objectsubject", "objectpredicate", "objectobject");
      Mutation m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12;

      m1 = new Mutation(s1 + DELIM + "1");
      m1.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m2 = new Mutation(s2 + DELIM + "1");
      m2.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m3 = new Mutation(s3 + DELIM + "1");
      m3.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m4 = new Mutation(s4 + DELIM + "1");
      m4.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m5 = new Mutation(s5 + DELIM + "1");
      m5.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m6 = new Mutation(s6 + DELIM + "1");
      m6.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m7 = new Mutation(s7 + DELIM + "1");
      m7.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m8 = new Mutation(s8 + DELIM + "1");
      m8.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m9 = new Mutation(s9 + DELIM + "1");
      m9.put(new Text("count"), new Text(""), new Value("2".getBytes()));
      m10 = new Mutation(s10 + DELIM + "1");
      m10.put(new Text("count"), new Text(""), new Value("1".getBytes()));
      m11 = new Mutation(s11 + DELIM + "1");
      m11.put(new Text("count"), new Text(""), new Value("2".getBytes()));

      mList.add(m1);
      mList.add(m2);
      mList.add(m3);
      mList.add(m4);
      mList.add(m5);
      mList.add(m6);
      mList.add(m7);
      mList.add(m8);
      mList.add(m9);
      mList.add(m10);
      mList.add(m11);

      bw1.addMutations(mList);
      bw1.close();

      m1 = new Mutation(s1);
      m2 = new Mutation(s2);
      m3 = new Mutation(s3);
      m4 = new Mutation(s4);
      m5 = new Mutation(s5);
      m6 = new Mutation(s6);
      m7 = new Mutation(s7);
      m8 = new Mutation(s8);
      m9 = new Mutation(s9);
      m10 = new Mutation(s10);
      m11 = new Mutation(s11);
      m12 = new Mutation(new Text("subjectpredicateobject" + DELIM + "FullTableCardinality"));
      m12.put(new Text("FullTableCardinality"), new Text("100"), EMPTY_VAL);

      for (String s : sList) {

        m1.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m2.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m3.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m4.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m5.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m6.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m7.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);
        m8.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);
        m9.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);
        m10.put(new Text(s), new Text(Integer.toString(1)), EMPTY_VAL);
        m11.put(new Text(s), new Text(Integer.toString(2)), EMPTY_VAL);

      }
      mList2.add(m1);
      mList2.add(m2);
      mList2.add(m3);
      mList2.add(m4);
      mList2.add(m5);
      mList2.add(m6);
      mList2.add(m7);
      mList2.add(m8);
      mList2.add(m9);
      mList2.add(m10);
      mList2.add(m11);
      mList2.add(m12);
      bw2.addMutations(mList2);
      bw2.close();

      TupleExpr te = getTupleExpr(q9);
      System.out.println(te);
      (new FilterOptimizer()).optimize(te,null,null);

      EntityOptimizer cco = new EntityOptimizer(accc);
      System.out.println("Originial query is " + te);
      cco.optimize(te, null, null);

      EntityCentricVisitor ccv = new EntityCentricVisitor();
      te.visit(ccv);

      List<QueryModelNode> nodes = Lists.newArrayList(ccv.getCcNodes());

      Assert.assertEquals(3, nodes.size());
      List<String> cVarList = Lists.newArrayList();
      cVarList.add("i");
      cVarList.add("m");

      for(QueryModelNode q: nodes) {

          if(((EntityTupleSet)q).getStarQuery().getNodes().size() == 2) {
              String s = ((EntityTupleSet)q).getStarQuery().getCommonVarName();
              System.out.println("node is " + q  + " and common var is " + s);
              System.out.println("star query is " + ((EntityTupleSet)q).getStarQuery());
              Assert.assertTrue(cVarList.contains(s));
              cVarList.remove(s);
          } else if(((EntityTupleSet)q).getStarQuery().getNodes().size() == 3) {
              Assert.assertEquals("h", ((EntityTupleSet)q).getStarQuery().getCommonVarName());
          } else {
              Assert.assertTrue(false);
          }
      }

      System.out.println(te);

    }

    private TupleExpr getTupleExpr(String query) throws MalformedQueryException {

        SPARQLParser sp = new SPARQLParser();
        ParsedQuery pq = sp.parseQuery(query, null);

        return pq.getTupleExpr();
      }

    private class EntityCentricVisitor extends AbstractQueryModelVisitor<RuntimeException> {

        private Set<QueryModelNode> ccNodes = Sets.newHashSet();

        public Set<QueryModelNode> getCcNodes() {
            return ccNodes;
        }

        public void meetNode(QueryModelNode node) {

            if(node instanceof EntityTupleSet) {
                ccNodes.add(node);
            }

            super.meetNode(node);
        }

    }

}


text:
using System;
using System.Collections.Generic;
using System.Text;

namespace InheritanceAndPolymorphism
{
    public abstract class Course
    {
        private string courseName;
        private string teacherName;
        private List<string> students;

        public Course(string courseName, string teacherName, List<string> students)
        {
            this.CoureseName = courseName;
            this.TeacherName = teacherName;
            this.Students = students;
        }

        public Course(string courseName)
        {
            this.CoureseName = this.courseName;
            this.TeacherName = this.teacherName;
            this.Students = new List<string>();

            for (int i = 0; i < this.Students.Count; i++)
            {
                this.AddStudent(this.Students[i]);
            }
        }

        public Course(string courseName, string teacherName)
        {
            this.CoureseName = courseName;
            this.TeacherName = teacherName;
            this.Students = new List<string>();

            for (int i = 0; i < this.Students.Count; i++)
            {
                this.AddStudent(this.Students[i]);
            }
        }

        public string CoureseName
        {
            get
            {
                return this.courseName;
            }

            set
            {
                this.courseName = value;
            }
        }

        public string TeacherName
        {
            get
            {
                return this.teacherName;
            }

            set
            {
                this.teacherName = value;
            }
        }

        public List<string> Students { get; set; }

        public void AddStudent(string name)
        {
            if (name == null || name.Length == 0)
            {
                throw new ArgumentException("Student name cannot be null or empty");
            }

            this.Students.Add(name);
        }

        public override string ToString()
        {
            StringBuilder result = new StringBuilder();
            result.Append(this.CoureseName);

            if (this.TeacherName != null)
            {
                result.Append("; Teacher = ");
                result.Append(this.TeacherName);
            }

            result.Append("; Students = ");
            result.Append(this.GetStudentsAsString());

            return result.ToString();
        }

        private string GetStudentsAsString()
        {
            if (this.Students.Count == 0)
            {
                return "{ }";
            }
            else
            {
                return "{ " + string.Join(", ", this.Students) + " }";
            }
        }
    }
}