text:
package ambex

/**********************************************
 * ambex: Ambassador Experimental ADS server
 *
 * Here's the deal.
 *
 * go-control-plane, several different classes manage this stuff:
 *
 * - The root of the world is a SnapshotCache.
 *   - import github.com/datawire/ambassador/pkg/envoy-control-plane/cache/v2, then refer
 *     to cache.SnapshotCache.
 *   - A collection of internally consistent configuration objects is a
 *     Snapshot (cache.Snapshot).
 *   - Snapshots are collected in the SnapshotCache.
 *   - A given SnapshotCache can hold configurations for multiple Envoys,
 *     identified by the Envoy 'node ID', which must be configured for the
 *     Envoy.
 * - The SnapshotCache can only hold go-control-plane configuration objects,
 *   so you have to build these up to hand to the SnapshotCache.
 * - The gRPC stuff is handled by a Server.
 *   - import github.com/datawire/ambassador/pkg/envoy-control-plane/server, then refer
 *     to server.Server.
 *   - Our runManagementServer (largely ripped off from the go-control-plane
 *     tests) gets this running. It takes a SnapshotCache (cleverly called a
 *     "config" for no reason I understand) and a gRPCServer as arguments.
 *   - _ALL_ the gRPC madness is handled by the Server, with the assistance
 *     of the methods in a callback object.
 * - Once the Server is running, Envoy can open a gRPC stream to it.
 *   - On connection, Envoy will get handed the most recent Snapshot that
 *     the Server's SnapshotCache knows about.
 *   - Whenever a newer Snapshot is added to the SnapshotCache, that Snapshot
 *     will get sent to the Envoy.
 * - We manage the SnapshotCache by loading envoy configuration from
 *   json and/or protobuf files on disk.
 *   - By default when we get a SIGHUP, we reload configuration.
 *   - When passed the -watch argument we reload whenever any file in
 *     the directory changes.
 */

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"os/signal"
	"path/filepath"
	"reflect"
	"strings"
	"syscall"

	"github.com/fsnotify/fsnotify"
	"github.com/sirupsen/logrus"
	"google.golang.org/grpc"

	// protobuf library
	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"
	"github.com/golang/protobuf/ptypes/any"

	// envoy control plane
	"github.com/datawire/ambassador/pkg/envoy-control-plane/cache/types"
	ctypes "github.com/datawire/ambassador/pkg/envoy-control-plane/cache/types"
	v2cache "github.com/datawire/ambassador/pkg/envoy-control-plane/cache/v2"
	v3cache "github.com/datawire/ambassador/pkg/envoy-control-plane/cache/v3"
	v2server "github.com/datawire/ambassador/pkg/envoy-control-plane/server/v2"
	v3server "github.com/datawire/ambassador/pkg/envoy-control-plane/server/v3"
	"github.com/datawire/ambassador/pkg/memory"

	// envoy protobuf v2 -- Be sure to import the package of any types that the Python emits a
	// "@type" of in the generated config, even if that package is otherwise not used by ambex.
	v2 "github.com/datawire/ambassador/pkg/api/envoy/api/v2"
	_ "github.com/datawire/ambassador/pkg/api/envoy/api/v2/auth"
	v2core "github.com/datawire/ambassador/pkg/api/envoy/api/v2/core"
	_ "github.com/datawire/ambassador/pkg/api/envoy/config/accesslog/v2"
	v2bootstrap "github.com/datawire/ambassador/pkg/api/envoy/config/bootstrap/v2"
	_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/buffer/v2"
	_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/ext_authz/v2"
	_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/gzip/v2"
	_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/lua/v2"
	_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/rate_limit/v2"
	_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/rbac/v2"
	_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/router/v2"
	_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/network/http_connection_manager/v2"
	_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/network/tcp_proxy/v2"
	v2discovery "github.com/datawire/ambassador/pkg/api/envoy/service/discovery/v2"

	// Envoy API v3
	//
	// XXX TODO Is this actually true and necessary?
	// yes it is true and necessary. need to import all types so they can be decoded by `decode`
	// Be sure to import the package of any types that the Python
	// emits a "@type" of in the generated config, even if that package is otherwise
	// not used by ambex.
	_ "github.com/datawire/ambassador/pkg/api/envoy/config/accesslog/v3"
	v3bootstrap "github.com/datawire/ambassador/pkg/api/envoy/config/bootstrap/v3"
	v3clusterconfig "github.com/datawire/ambassador/pkg/api/envoy/config/cluster/v3"
	v3core "github.com/datawire/ambassador/pkg/api/envoy/config/core/v3"
	v3endpointconfig "github.com/datawire/ambassador/pkg/api/envoy/config/endpoint/v3"
	v3listenerconfig "github.com/datawire/ambassador/pkg/api/envoy/config/listener/v3"
	v3routeconfig "github.com/datawire/ambassador/pkg/api/envoy/config/route/v3"
	_ "github.com/datawire/ambassador/pkg/api/envoy/extensions/access_loggers/file/v3"
	_ "github.com/datawire/ambassador/pkg/api/envoy/extensions/access_loggers/grpc/v3"
	_ "github.com/datawire/ambassador/pkg/api/envoy/extensions/filters/http/buffer/v3"
	_ "github.com/datawire/ambassador/pkg/api/envoy/extensions/filters/http/ext_authz/v3"
	_ "github.com/datawire/ambassador/pkg/api/envoy/extensions/filters/http/grpc_stats/v3"
	_ "github.com/datawire/ambassador/pkg/api/envoy/extensions/filters/http/gzip/v3"
	_ "github.com/datawire/ambassador/pkg/api/envoy/extensions/filters/http/lua/v3"
	_ "github.com/datawire/ambassador/pkg/api/envoy/extensions/filters/http/ratelimit/v3"
	_ "github.com/datawire/ambassador/pkg/api/envoy/extensions/filters/http/rbac/v3"
	_ "github.com/datawire/ambassador/pkg/api/envoy/extensions/filters/http/router/v3"
	_ "github.com/datawire/ambassador/pkg/api/envoy/extensions/filters/network/http_connection_manager/v3"
	_ "github.com/datawire/ambassador/pkg/api/envoy/extensions/filters/network/tcp_proxy/v3"
	v3cluster "github.com/datawire/ambassador/pkg/api/envoy/service/cluster/v3"
	v3discovery "github.com/datawire/ambassador/pkg/api/envoy/service/discovery/v3"
	v3endpoint "github.com/datawire/ambassador/pkg/api/envoy/service/endpoint/v3"
	v3listener "github.com/datawire/ambassador/pkg/api/envoy/service/listener/v3"
	v3route "github.com/datawire/ambassador/pkg/api/envoy/service/route/v3"
	v3runtime "github.com/datawire/ambassador/pkg/api/envoy/service/runtime/v3"

	// envoy protobuf v3 -- likewise
	_ "github.com/datawire/ambassador/pkg/api/envoy/extensions/filters/http/response_map/v3"

	// first-party libraries
	"github.com/datawire/dlib/dhttp"
)

type Args struct {
	debug bool
	watch bool

	adsNetwork string
	adsAddress string

	dirs []string
}

func parseArgs(rawArgs ...string) (*Args, error) {
	var args Args
	flagset := flag.NewFlagSet("ambex", flag.ContinueOnError)

	flagset.BoolVar(&args.debug, "debug", false, "Use debug logging")
	flagset.BoolVar(&args.watch, "watch", false, "Watch for file changes")

	// TODO(lukeshu): Consider changing the default here so we don't need to put it in entrypoint.sh
	flagset.StringVar(&args.adsNetwork, "ads-listen-network", "tcp", "network for ADS to listen on")
	flagset.StringVar(&args.adsAddress, "ads-listen-address", ":18000", "address (on --ads-listen-network) for ADS to listen on")

	var legacyAdsPort uint
	flagset.UintVar(&legacyAdsPort, "ads", 0, "port number for ADS to listen on--deprecated, use --ads-listen-address=:1234 instead")

	if err := flagset.Parse(rawArgs); err != nil {
		return nil, err
	}

	if legacyAdsPort != 0 {
		args.adsAddress = fmt.Sprintf(":%v", legacyAdsPort)
	}

	args.dirs = flagset.Args()
	if len(args.dirs) == 0 {
		args.dirs = []string{"."}
	}

	return &args, nil
}

// Hasher returns node ID as an ID
type HasherV2 struct {
}

// ID function
func (h HasherV2) ID(node *v2core.Node) string {
	if node == nil {
		return "unknown"
	}
	return node.Id
}

// Hasher returns node ID as an ID
type HasherV3 struct {
}

// ID function
func (h HasherV3) ID(node *v3core.Node) string {
	if node == nil {
		return "unknown"
	}
	return node.Id
}

// end Hasher stuff

// This feels kinda dumb.
type loggerv2 struct {
	*logrus.Logger
}

var log = &loggerv2{
	Logger: logrus.StandardLogger(),
}

type loggerv3 struct {
	*logrus.Logger
}

var logv3 = &loggerv3{
	Logger: logrus.StandardLogger(),
}

// run stuff
// RunManagementServer starts an xDS server at the given port.
func runManagementServer(ctx context.Context, server v2server.Server, serverv3 v3server.Server, adsNetwork, adsAddress string) {
	grpcServer := grpc.NewServer()

	lis, err := net.Listen(adsNetwork, adsAddress)
	if err != nil {
		log.WithError(err).Panic("failed to listen")
	}

	// register services
	v2discovery.RegisterAggregatedDiscoveryServiceServer(grpcServer, server)
	v2.RegisterEndpointDiscoveryServiceServer(grpcServer, server)
	v2.RegisterClusterDiscoveryServiceServer(grpcServer, server)
	v2.RegisterRouteDiscoveryServiceServer(grpcServer, server)
	v2.RegisterListenerDiscoveryServiceServer(grpcServer, server)

	v3discovery.RegisterAggregatedDiscoveryServiceServer(grpcServer, serverv3)
	v3endpoint.RegisterEndpointDiscoveryServiceServer(grpcServer, serverv3)
	v3cluster.RegisterClusterDiscoveryServiceServer(grpcServer, serverv3)
	v3route.RegisterRouteDiscoveryServiceServer(grpcServer, serverv3)
	v3listener.RegisterListenerDiscoveryServiceServer(grpcServer, serverv3)

	log.WithFields(logrus.Fields{"addr": adsNetwork + ":" + adsAddress}).Info("Listening")
	go func() {
		sc := &dhttp.ServerConfig{
			Handler: grpcServer,
		}
		if err := sc.Serve(ctx, lis); err != nil {
			log.WithFields(logrus.Fields{"error": err}).Error("Management server exited")
		}
	}()
}

// Decoders for unmarshalling our config
var decoders = map[string](func(string, proto.Message) error){
	".json": jsonpb.UnmarshalString,
	".pb":   proto.UnmarshalText,
}

func isDecodable(name string) bool {
	if strings.HasPrefix(name, ".") {
		return false
	}

	ext := filepath.Ext(name)
	_, ok := decoders[ext]
	return ok
}

// Not sure if there is a better way to do this, but we cast to this
// so we can call the generated Validate method.
type Validatable interface {
	proto.Message
	Validate() error
}

func Decode(name string) (proto.Message, error) {
	any := &any.Any{}
	contents, err := ioutil.ReadFile(name)
	if err != nil {
		return nil, err
	}

	ext := filepath.Ext(name)
	decoder := decoders[ext]
	err = decoder(string(contents), any)
	if err != nil {
		return nil, err
	}

	var m ptypes.DynamicAny
	err = ptypes.UnmarshalAny(any, &m)
	if err != nil {
		return nil, err
	}

	var v = m.Message.(Validatable)

	err = v.Validate()
	if err != nil {
		return nil, err
	}
	log.Infof("Loaded file %s", name)
	return v, nil
}

func Merge(to, from proto.Message) {
	str, err := (&jsonpb.Marshaler{}).MarshalToString(from)
	if err != nil {
		panic(err)
	}
	err = jsonpb.UnmarshalString(str, to)
	if err != nil {
		panic(err)
	}
}

func Clone(src proto.Message) proto.Message {
	in := reflect.ValueOf(src)
	if in.IsNil() {
		return src
	}
	out := reflect.New(in.Type().Elem())
	dst := out.Interface().(proto.Message)
	Merge(dst, src)
	return dst
}

func update(ctx context.Context, config v2cache.SnapshotCache, configv3 v3cache.SnapshotCache, generation *int, dirs []string, edsEndpoints map[string]*v2.ClusterLoadAssignment, edsEndpointsV3 map[string]*v3endpointconfig.ClusterLoadAssignment, fastpathSnapshot *FastpathSnapshot, updates chan<- Update) {
	clusters := []ctypes.Resource{}  // v2.Cluster
	routes := []ctypes.Resource{}    // v2.RouteConfiguration
	listeners := []ctypes.Resource{} // v2.Listener
	runtimes := []ctypes.Resource{}  // discovery.Runtime

	clustersv3 := []ctypes.Resource{}  // v3.Cluster
	routesv3 := []ctypes.Resource{}    // v3.RouteConfiguration
	listenersv3 := []ctypes.Resource{} // v3.Listener
	runtimesv3 := []ctypes.Resource{}  // v3.Runtime

	var filenames []string

	for _, dir := range dirs {
		files, err := ioutil.ReadDir(dir)
		if err != nil {
			log.WithError(err).Warnf("Error listing %v", dir)
			continue
		}
		for _, file := range files {
			name := file.Name()
			if isDecodable(name) {
				filenames = append(filenames, filepath.Join(dir, name))
			}
		}
	}

	for _, name := range filenames {
		m, e := Decode(name)
		if e != nil {
			log.Warnf("%s: %v", name, e)
			continue
		}
		var dst *[]ctypes.Resource
		switch m.(type) {
		case *v2.Cluster:
			dst = &clusters
		case *v2.RouteConfiguration:
			dst = &routes
		case *v2.Listener:
			dst = &listeners
		case *v2discovery.Runtime:
			dst = &runtimes
		case *v2bootstrap.Bootstrap:
			bs := m.(*v2bootstrap.Bootstrap)
			sr := bs.StaticResources
			for _, lst := range sr.Listeners {
				// When the RouteConfiguration is embedded in the listener, it will cause envoy to
				// go through a complete drain cycle whenever there is a routing change and that
				// will potentially disrupt in-flight requests. By converting all listeners to use
				// RDS rather than inlining their routing configuration, we significantly reduce the
				// set of circumstances where the listener definition itself changes, and this in
				// turn reduces the set of circumstances where envoy has to go through that drain
				// process and disrupt in-flight requests.
				rdsListener, routeConfigs, err := ListenerToRdsListener(lst)
				if err != nil {
					log.Errorf("Error converting listener to RDS: %+v", err)
					listeners = append(listeners, Clone(lst).(ctypes.Resource))
					continue
				}
				listeners = append(listeners, rdsListener)
				for _, rc := range routeConfigs {
					// These routes will get included in the configuration snapshot created below.
					routes = append(routes, rc)
				}
			}
			for _, cls := range sr.Clusters {
				clusters = append(clusters, Clone(cls).(ctypes.Resource))
			}
			continue
		case *v3clusterconfig.Cluster:
			dst = &clustersv3
		case *v3routeconfig.RouteConfiguration:
			dst = &routesv3
		case *v3listenerconfig.Listener:
			dst = &listenersv3
		case *v3runtime.Runtime:
			dst = &runtimesv3
		case *v3bootstrap.Bootstrap:
			bs := m.(*v3bootstrap.Bootstrap)
			sr := bs.StaticResources
			for _, lst := range sr.Listeners {
				// When the RouteConfiguration is embedded in the listener, it will cause envoy to
				// go through a complete drain cycle whenever there is a routing change and that
				// will potentially disrupt in-flight requests. By converting all listeners to use
				// RDS rather than inlining their routing configuration, we significantly reduce the
				// set of circumstances where the listener definition itself changes, and this in
				// turn reduces the set of circumstances where envoy has to go through that drain
				// process and disrupt in-flight requests.
				rdsListener, routeConfigs, err := V3ListenerToRdsListener(lst)
				if err != nil {
					log.Errorf("Error converting listener to RDS: %+v", err)
					listenersv3 = append(listenersv3, Clone(lst).(ctypes.Resource))
					continue
				}
				listenersv3 = append(listenersv3, rdsListener)
				for _, rc := range routeConfigs {
					// These routes will get included in the configuration snapshot created below.
					routesv3 = append(routesv3, rc)
				}
			}
			for _, cls := range sr.Clusters {
				clustersv3 = append(clustersv3, Clone(cls).(ctypes.Resource))
			}
			continue
		default:
			log.Warnf("Unrecognized resource %s: %v", name, e)
			continue
		}
		*dst = append(*dst, m.(ctypes.Resource))
	}

	if fastpathSnapshot != nil && fastpathSnapshot.Snapshot != nil {
		for _, lst := range fastpathSnapshot.Snapshot.Resources[types.Listener].Items {
			listeners = append(listeners, lst)
		}
		for _, route := range fastpathSnapshot.Snapshot.Resources[types.Route].Items {
			routes = append(routes, route)
		}
		for _, clu := range fastpathSnapshot.Snapshot.Resources[types.Cluster].Items {
			clusters = append(clusters, clu)
		}
		// We intentionally omit endpoints since those are carried separately.
	}

	// The configuration data that reaches us here arrives via two parallel paths that race each
	// other. The endpoint data comes in realtime directly from the golang watcher in the entrypoint
	// package. The cluster configuration comes from the python code. Either one can win which means
	// we might at times see endpoint data with no corresponding cluster and we might also see
	// clusters with no corresponding endpoint data. Both of these circumstances should be
	// transient.
	//
	// To produce a consistent configuration we do an outer join operation on the endpoint and
	// cluster configuration that we have at this moment. If there is no endpoint information for a
	// given cluster, we will synthesize an empty ClusterLoadAssignment.
	//
	// Note that a cluster not existing is very different to envoy than a cluster existing but
	// having an empty ClusterLoadAssignment. When envoy first discovers clusters it goes through a
	// warmup process to be sure the cluster is properly bootstrapped before routing traffic to
	// it. See here for more details:
	//
	// https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/cluster_manager.html?highlight=cluster%20warming
	//
	// For this reason if there is no endpoint data for the cluster we will synthesize an empty
	// ClusterLoadAssignment rather than filtering out the cluster. This avoids triggering the
	// warmup sequence in scenarios where the endpoint data for a cluster is really flapping into
	// and out of existence. In that circumstance we want to faithfully relay to envoy that the
	// cluster exists but currently has no endpoints.
	endpoints := JoinEdsClusters(ctx, clusters, edsEndpoints)
	endpointsv3 := JoinEdsClustersV3(ctx, clustersv3, edsEndpointsV3)

	// Create a new configuration snapshot from everything we have just loaded from disk.
	version := fmt.Sprintf("v%d", *generation)
	*generation++
	snapshot := v2cache.NewSnapshot(
		version,
		endpoints,
		clusters,
		routes,
		listeners,
		runtimes)

	if err := snapshot.Consistent(); err != nil {
		bs, _ := json.Marshal(snapshot)
		log.Errorf("V2 Snapshot inconsistency: %v: %s", err, bs)
		return
	}

	snapshotv3 := v3cache.NewSnapshot(
		version,
		endpointsv3,
		clustersv3,
		routesv3,
		listenersv3,
		runtimesv3)

	if err := snapshotv3.Consistent(); err != nil {
		bs, _ := json.Marshal(snapshotv3)
		log.Errorf("V3 Snapshot inconsistency: %v: %s", err, bs)
		return
	}

	// This used to just directly update envoy. Since we want ratelimiting, we now send an
	// Update object down the channel with a function that knows how to do the update if/when
	// the ratelimiting logic decides.
	//
	// We also need to pay attention to contexts here so we can shutdown properly. If we didn't
	// have the context portion, the ratelimit goroutine could shutdown first and we could end
	// up blocking here and never shutting down.
	select {
	case updates <- Update{version, func() error {
		err := config.SetSnapshot("test-id", snapshot)
		if err != nil {
			return fmt.Errorf("V2 Snapshot error %q for %+v", err, snapshot)
		}

		err = configv3.SetSnapshot("test-id", snapshotv3)
		if err != nil {
			return fmt.Errorf("V3 Snapshot error %q for %+v", err, snapshotv3)
		}

		return nil
	}}:
	case <-ctx.Done():
	}
}

func warn(err error) bool {
	if err != nil {
		log.Warn(err)
		return true
	} else {
		return false
	}
}

// OnStreamOpen is called once an xDS stream is open with a stream ID and the type URL (or "" for ADS).
func (l loggerv2) OnStreamOpen(_ context.Context, sid int64, stype string) error {
	l.Infof("V2 Stream open[%v]: %v", sid, stype)
	return nil
}

func (l loggerv3) OnStreamOpen(_ context.Context, sid int64, stype string) error {
	l.Infof("V3 Stream open[%v]: %v", sid, stype)
	return nil
}

// OnStreamClosed is called immediately prior to closing an xDS stream with a stream ID.
func (l loggerv2) OnStreamClosed(sid int64) {
	l.Infof("V2 Stream closed[%v]", sid)
}

func (l loggerv3) OnStreamClosed(sid int64) {
	l.Infof("V3 Stream closed[%v]", sid)
}

// OnStreamRequest is called once a request is received on a stream.
func (l loggerv2) OnStreamRequest(sid int64, req *v2.DiscoveryRequest) error {
	l.Infof("V2 Stream request[%v] for type %s: requesting %d resources", sid, req.TypeUrl, len(req.ResourceNames))
	l.Debugf("V2 Stream request[%v] dump: %v", sid, req)
	return nil
}

func (l loggerv3) OnStreamRequest(sid int64, req *v3discovery.DiscoveryRequest) error {
	l.Infof("V3 Stream request[%v] for type %s: requesting %d resources", sid, req.TypeUrl, len(req.ResourceNames))
	l.Debugf("V3 Stream request[%v] dump: %v", sid, req)
	return nil
}

// OnStreamResponse is called immediately prior to sending a response on a stream.
func (l loggerv2) OnStreamResponse(sid int64, req *v2.DiscoveryRequest, res *v2.DiscoveryResponse) {
	l.Infof("V2 Stream response[%v] for type %s: returning %d resources", sid, res.TypeUrl, len(res.Resources))
	l.Debugf("V2 Stream dump response[%v]: %v -> %v", sid, req, res)
}

func (l loggerv3) OnStreamResponse(sid int64, req *v3discovery.DiscoveryRequest, res *v3discovery.DiscoveryResponse) {
	l.Infof("V3 Stream response[%v] for type %s: returning %d resources", sid, res.TypeUrl, len(res.Resources))
	l.Debugf("V3 Stream dump response[%v]: %v -> %v", sid, req, res)
}

// OnFetchRequest is called for each Fetch request
func (l loggerv2) OnFetchRequest(_ context.Context, r *v2.DiscoveryRequest) error {
	l.Infof("V2 Fetch request: %v", r)
	return nil
}

func (l loggerv3) OnFetchRequest(_ context.Context, r *v3discovery.DiscoveryRequest) error {
	l.Infof("V3 Fetch request: %v", r)
	return nil
}

// OnFetchResponse is called immediately prior to sending a response.
func (l loggerv2) OnFetchResponse(req *v2.DiscoveryRequest, res *v2.DiscoveryResponse) {
	l.Infof("V2 Fetch response: %v -> %v", req, res)
}

func (l loggerv3) OnFetchResponse(req *v3discovery.DiscoveryRequest, res *v3discovery.DiscoveryResponse) {
	l.Infof("V3 Fetch response: %v -> %v", req, res)
}

func Main(ctx context.Context, Version string, rawArgs ...string) error {
	usage := memory.GetMemoryUsage()
	go usage.Watch(ctx)
	return Main2(ctx, Version, usage.PercentUsed, make(chan *FastpathSnapshot), rawArgs...)
}

func Main2(ctx context.Context, Version string, getUsage MemoryGetter, fastpathCh <-chan *FastpathSnapshot,
	rawArgs ...string) error {
	args, err := parseArgs(rawArgs...)
	if err != nil {
		return err
	}

	if args.debug {
		log.SetLevel(logrus.DebugLevel)
	} else {
		log.SetLevel(logrus.WarnLevel)
	}

	log.Infof("Ambex %s starting...", Version)

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.WithError(err).Panic()
	}
	defer watcher.Close()

	if args.watch {
		for _, d := range args.dirs {
			watcher.Add(d)
		}
	}

	// The golang signal package does not block when it writes to the channel. We therefore need a
	// nonzero buffer for the channel to minimize the possiblity that we miss out on a signal that
	// comes in while we are doing work and not reading from the channel. Since we are subscribing
	// to multiple signals there is also the possibility that even with buffering, too many of one
	// kind of signal can fill up the buffer and cause us to drop an occurance of the other types of
	// signal. To minimize the chance of that happening we will choose a buffer size of 100. That
	// may well be overkill, but better to not have to consider the possibility that we lose a
	// signal.
	ch := make(chan os.Signal, 100)
	signal.Notify(ch, syscall.SIGHUP, os.Interrupt, syscall.SIGTERM)

	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	config := v2cache.NewSnapshotCache(true, HasherV2{}, log)
	configv3 := v3cache.NewSnapshotCache(true, HasherV3{}, logv3)
	server := v2server.NewServer(ctx, config, log)
	serverv3 := v3server.NewServer(ctx, configv3, logv3)

	runManagementServer(ctx, server, serverv3, args.adsNetwork, args.adsAddress)

	pid := os.Getpid()
	file := "ambex.pid"
	if !warn(ioutil.WriteFile(file, []byte(fmt.Sprintf("%v", pid)), 0644)) {
		log.WithFields(logrus.Fields{"pid": pid, "file": file}).Info("Wrote PID")
	}

	updates := make(chan Update)
	envoyUpdaterDone := make(chan struct{})
	go func() {
		defer close(envoyUpdaterDone)
		err := Updater(ctx, updates, getUsage)
		if err != nil {
			// Panic will get reported more usefully by entrypoint.go's exit code than logging the
			// error.
			panic(err)
		}
	}()

	generation := 0
	var fastpathSnapshot *FastpathSnapshot
	edsEndpoints := map[string]*v2.ClusterLoadAssignment{}
	edsEndpointsV3 := map[string]*v3endpointconfig.ClusterLoadAssignment{}
	update(ctx, config, configv3, &generation, args.dirs, edsEndpoints, edsEndpointsV3, fastpathSnapshot, updates)

OUTER:
	for {

		select {
		case sig := <-ch:
			switch sig {
			case syscall.SIGHUP:
				update(ctx, config, configv3, &generation, args.dirs, edsEndpoints, edsEndpointsV3, fastpathSnapshot, updates)
			case os.Interrupt, syscall.SIGTERM:
				break OUTER
			}
		case fpSnap := <-fastpathCh:
			if fpSnap.Endpoints != nil {
				edsEndpoints = fpSnap.Endpoints.ToMap_v2()
				edsEndpointsV3 = fpSnap.Endpoints.ToMap_v3()
			}
			fastpathSnapshot = fpSnap
			update(ctx, config, configv3, &generation, args.dirs, edsEndpoints, edsEndpointsV3, fastpathSnapshot, updates)
		case <-watcher.Events:
			update(ctx, config, configv3, &generation, args.dirs, edsEndpoints, edsEndpointsV3, fastpathSnapshot, updates)
		case err := <-watcher.Errors:
			log.WithError(err).Warn("Watcher error")
		case <-ctx.Done():
			break OUTER
		}

	}

	<-envoyUpdaterDone
	log.Info("Done")
	return nil
}


text:
package org.rhq.lab.ircbot;

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

import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;
import org.pircbotx.Configuration;
import org.pircbotx.Configuration.Builder;
import org.pircbotx.PircBotX;
import org.pircbotx.hooks.Listener;
import org.pircbotx.hooks.ListenerAdapter;

public class App extends ListenerAdapter<PircBotX> implements Listener<PircBotX> {

	@Option(name="-s",usage="irc server", metaVar="string")
	private String ircServer;

	@Option(name="-n",usage="irc nick",  metaVar="string")
	private String ircNick="rhqlab-bot";

	@Argument(usage="supply a list of irc channels",  metaVar="main parameter")
	protected List<String> ircChannels = new ArrayList<String>();

	public void start() {
    	Builder<PircBotX> config = new Configuration.Builder<PircBotX>()
    	        .setName(ircNick)
    	        .setAutoNickChange(true)
    	        .setServer(ircServer, 6667)
    	        .addListener(new RHQLabCommandHandler());

    	for(String channel:ircChannels) {
    		config.addAutoJoinChannel(channel);
    	}

    	PircBotX myBot = new PircBotX(config.buildConfiguration());

    	try {
    		myBot.startBot();
    	} catch (Exception e) {
   			e.printStackTrace();
    	}
	}

    public static void main( String[] args ){

    	App app = new App();
    	CmdLineParser parser = new CmdLineParser(app);
    	try {
			parser.parseArgument(args);
			if (app.ircChannels.isEmpty()) {
				throw new CmdLineException(parser, "Missing irc channel(s)");
			}
	    	app.start();
		} catch (CmdLineException e) {
			System.err.println(e.getMessage());
			System.err.println("Usage: -s <server> -n <nick>  #channel1 #channel2...");
			System.err.println();
		}

    }

}

redpajama_set_name: RedPajamaGithub


text:
package org.dashbuilder.dataset.impl;

import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;

import org.dashbuilder.dataset.ColumnType;
import org.dashbuilder.dataset.DataColumn;
import org.dashbuilder.dataset.DataSet;
import org.dashbuilder.dataset.DataSetMetadata;
import org.dashbuilder.dataset.def.DataSetDef;
import org.dashbuilder.dataset.group.GroupFunction;
import org.jboss.errai.common.client.api.annotations.Portable;

import javax.validation.constraints.NotNull;

@Portable
public class DataSetImpl implements DataSet {

    protected DataSetDef definition;

    @NotNull(message = "{dataSetApi_dataSetImpl_uuid_notNull}")
    protected String uuid = null;

    @NotNull(message = "{dataSetApi_dataSetImpl_creationDate_notNull}")
    protected Date creationDate = new Date();

    protected List<DataColumnImpl> columns = new ArrayList<DataColumnImpl>();
    protected int rowCountNonTrimmed = -1;

    public DataSetMetadata getMetadata() {
        return new DataSetMetadataImpl(this);
    }

    public DataSetDef getDefinition() {
        return definition;
    }

    public void setDefinition(DataSetDef definition) {
        this.definition = definition;
    }

    public String getUUID() {
        return uuid;
    }

    public void setUUID(String uuid) {
        this.uuid = uuid;
    }

    public Date getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    public List<DataColumn> getColumns() {
        return new ArrayList<DataColumn>(columns);
    }

    public void setColumns(List<DataColumn> columnList) {
        columns.clear();
        for (DataColumn column : columnList) {
            columns.add((DataColumnImpl) column);
        }
    }

    public DataColumn getColumnById(String id) {
        for (DataColumn column : columns) {
            if (column.getId().equals(id)) return column;
            GroupFunction gf = column.getGroupFunction();
            if (gf != null && gf.getSourceId() != null && gf.getSourceId().equals(id)) {
                return column;
            }
        }
        return null;
    }

    public DataColumn getColumnByIndex(int index) {
        if (columns == null || columns.isEmpty()) {
            throw new IllegalArgumentException("The data set is empty.");
        }
        if (index >= columns.size()) {
            throw new IllegalArgumentException("The column index " + index + " is out of bounds: " + (columns.size()-1));
        }
        return columns.get(index);
    }

    @Override
    public int getColumnIndex( DataColumn dataColumn ) {
        if (dataColumn == null || "".equals(dataColumn.getId()) ) {
            throw new IllegalArgumentException("Wrong column specified.");
        }
        for (int i = 0; i < columns.size(); i++) {
            if ( dataColumn.getId().equalsIgnoreCase( columns.get( i ).getId() ) ) return i;
        }
        throw new IllegalArgumentException( "The column with id " + dataColumn.getId() + " does not exist." );
    }

    public DataSet addColumn(String id, ColumnType type) {
        return addColumn(id, type, null);
    }

    public DataSet addColumn(String id, ColumnType type, List values) {
        DataColumnImpl c = new DataColumnImpl();
        c.setDataSet(this);
        c.setId(id);
        c.setColumnType(type);
        if (values != null) c.setValues(values);
        columns.add(c);
        return this;
    }

    public DataSet addColumn(DataColumn column) {
        columns.add((DataColumnImpl) column);
        return this;
    }

    public DataSet removeColumn(String id) {
        Iterator<DataColumnImpl> it = columns.iterator();
        while (it.hasNext()) {
            DataColumn column = it.next();
            if (column.getId().equals(id)) {
                it.remove();
            }
        }
        return this;
    }

    public boolean isEmpty() {
        return getRowCount() == 0;
    }

    public int getRowCount() {
        if (columns == null || columns.isEmpty()) {
            return 0;
        }
        return columns.get(0).getValues().size();
    }

    public int getRowCountNonTrimmed() {
        if (rowCountNonTrimmed == -1) return getRowCount();
        return rowCountNonTrimmed;
    }

    public void setRowCountNonTrimmed(int rowCountNonTrimmed) {
        this.rowCountNonTrimmed = rowCountNonTrimmed;
    }

    public Object getValueAt(int row, String columnId) {
        DataColumn columnObj = getColumnById(columnId);
        return getValueAt(row, columnObj);
    }

    public Object getValueAt(int row, int column) {
        DataColumn columnObj = getColumnByIndex(column);
        return getValueAt(row, columnObj);
    }

    protected Object getValueAt(int row, DataColumn column) {
        if (row >= getRowCount()) {
            throw new IllegalArgumentException("The row index " + row + " is out of bounds: " + (getRowCount()-1));
        }
        return column.getValues().get(row);
    }

    public DataSet setValueAt(int row, int column, Object value) {
        _setValueAt(row, column, value, false);
        return this;
    }

    public DataSet addValueAt(int row, int column, Object value) {
        _setValueAt(row, column, value, true);
        return this;
    }

    public DataSet addValueAt(int column, Object value) {
        _setValueAt(-1, column, value, true);
        return this;
    }

    protected void _setValueAt(int row, int column, Object value, boolean insert) {
        DataColumn columnObj = getColumnByIndex(column);

        List l = columnObj.getValues();
        if (row > l.size()) {
            throw new IllegalArgumentException("The row index " + row + " is out of bounds: " + (l.size()-1));
        }

        if (row < 0 || row == l.size()) l.add(value);
        else if (insert) l.add(row, value);
        else l.set(row, value);
    }

    public DataSet setValuesAt(int row, Object... values) {
        _setValuesAt(row, false, values);
        return this;
    }

    public DataSet addValuesAt(int row, Object... values) {
        _setValuesAt(row, true, values);
        return this;
    }

    public DataSet addValues(Object... values) {
        _setValuesAt(-1, true, values);
        return this;
    }

    protected void _setValuesAt(int row, boolean insert, Object... values) {
        for (int i = 0; i < values.length; i++) {
            Object value = values[i];
            _setValueAt(row, i, value, insert);
        }
    }

    public DataSet addEmptyRowAt(int row) {
        _setEmptyRowAt(row, true);
        return this;
    }

    protected void _setEmptyRowAt(int row, boolean insert) {
        for (int i = 0; i < columns.size(); i++) {
            DataColumn column = columns.get(i);
            if (ColumnType.DATE.equals(column.getColumnType())) {
                _setValueAt(row, i, new Date(), insert);
            }
            else if (ColumnType.NUMBER.equals(column.getColumnType())) {
                _setValueAt(row, i, 0d, insert);
            }
            else {
                _setValueAt(row, i, "", insert);
            }
        }
    }

    public DataSet trim(int offset, int rows) {
        if (offset < 0) {
            throw new IllegalArgumentException("Offset can't be negative: " + offset);
        }
        if (offset == 0 && (rows <= 0 || rows >= this.getRowCount())) {
            this.rowCountNonTrimmed = -1;
            return this;
        }
        if (offset >= getRowCount()) {
            throw new IllegalArgumentException("Offset can't be greater than the number of rows: " + offset);
        }

        DataSetImpl other = cloneEmpty();
        other.rowCountNonTrimmed = getRowCount();
        for (int i=0; i<columns.size(); i++) {
            DataColumn column = columns.get(i);
            DataColumn colOther = other.getColumns().get(i);
            List values = column.getValues();
            List valOther = colOther.getValues();
            for (int j=offset; j<values.size() && j<( offset+rows ); j++) {
                Object value = values.get(j);
                valOther.add(value);
            }
        }
        return other;
    }

    public DataSet trim(List<Integer> rows) {
        if (rows == null) {
            return this;
        }
        DataSetImpl other = cloneEmpty();
        other.rowCountNonTrimmed = getRowCount();
        if (rows.isEmpty()) return other;

        for (int i=0; i<columns.size(); i++) {
            List values = columns.get(i).getValues();
            List valOther = other.getColumns().get(i).getValues();
            for (Integer row : rows) {
                if (row >= values.size()) {
                    throw new IllegalArgumentException("Row number is out of bounds: " + row);
                }
                Object value = values.get(row);
                valOther.add(value);
            }
        }
        return other;
    }

    public DataSetImpl cloneEmpty() {
        DataSetImpl other = new DataSetImpl();
        for (int i=0; i<columns.size(); i++) {
            DataColumn column = columns.get(i);
            DataColumn otherCol = column.cloneEmpty();
            other.addColumn(otherCol);
        }
        return other;
    }

    public DataSetImpl cloneInstance() {
        DataSetImpl other = new DataSetImpl();
        for (int i=0; i<columns.size(); i++) {
            DataColumn column = columns.get(i);
            DataColumn otherCol = column.cloneInstance();
            other.addColumn(otherCol);
        }
        return other;
    }

    public long getEstimatedSize() {
        int nrows = getRowCount();
        if (nrows == 0) return 0;

        List<DataColumn> columns = getColumns();
        int ncells = nrows * columns.size();
        int result = ncells * 4;
        for (int i = 0; i < columns.size(); i++) {
            Object firstRowValue = getValueAt(0, i);
            if (firstRowValue instanceof String) {
                for (int j = 0; j < nrows; j++) {
                    String stringValue = (String) getValueAt(j, i);
                    result += MemSizeEstimator.sizeOfString(stringValue);
                }
            } else {
                int singleValueSize = MemSizeEstimator.sizeOf(firstRowValue);
                result += nrows * singleValueSize;
            }
        }
        return result;
    }
}


text:
package ru.r2cloud.jradio.bsusat1;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import ru.r2cloud.jradio.util.LittleEndianDataInputStream;

public class RfCommandList {

	private List<RfCommand> commands;

	public RfCommandList() {
		// do nothing
	}

	public RfCommandList(LittleEndianDataInputStream dis) throws IOException {
		commands = new ArrayList<>(10);
		for (int i = 0; i < commands.size(); i++) {
			commands.add(new RfCommand(dis));
		}
	}

	public List<RfCommand> getCommands() {
		return commands;
	}

	public void setCommands(List<RfCommand> commands) {
		this.commands = commands;
	}
}


text:
using Akkomation.TelldusCore.Message;

namespace Akkomation.TelldusCore.Event
{
    internal class DeviceChangedEventProxy : EventProxyBase<DeviceChangedEventArgs>
    {
        // Since the delegate is used in unmanaged code, it is important to save a reference so that it does not get garbage collected
        private DeviceChangeEventDelegate OnDeviceChanged { get; }

        public DeviceChangedEventProxy(ITelldusCoreProxy proxy) : base(proxy)
        {
            OnDeviceChanged = (deviceId, changeEvent, changeType, callbackId, context) =>
            {
                SendEvent(() =>
                {
                    var change = GetDeviceChange(changeEvent, changeType);
                    return new DeviceChangedEventArgs(deviceId, change);
                });
            };
        }

        private static DeviceChange GetDeviceChange(int changeEvent, int changeType)
        {
            //This formula corresponds to the strange numbering of the DeviceChange enum
            return (DeviceChange)(changeEvent * 10 + changeType);
        }

        protected override int RegisterEvent()
        {
            return Proxy.RegisterDeviceChangeEvent(OnDeviceChanged);
        }
    }
}


text:
layout: post
title: Nullable schema if read avro files by spark
date: 2018-03-26 00:00:00 +00:00
tags: [avro, spark]
---
## Versions
Spark - 2.2

## Problem

If you read avro files by spark you can notice that in the resulted schema all fields are optional.

For example, if you read avro file with schema to dataframe

{% highlight json %}
{
	"type": "record",
	"name": "user",
	"namespace": "kakfa-avro.test",
	"fields": [
		{
			"name": "id",
			"type": "int"
		}
  ]
}
{% endhighlight %}

And then save dataframe to avro file back, then resulted schema will be:

{% highlight json %}
{
	"type": "record",
	"name": "user",
	"namespace": "kakfa-avro.test",
	"fields": [
		{
			"name": "id",
			"type": [
				"int",
				"null"
			]
		}
  ]
}
{% endhighlight %}

There is oen difference in the schema: the field id became optional. That is happening because of one line `dataSchema = dataSchema.asNullable` in DataSource class [source code](https://github.com/apache/spark/blob/master/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSource.scala)

{% highlight scala %}
HadoopFsRelation(
          fileCatalog,
          partitionSchema = partitionSchema,
          dataSchema = dataSchema.asNullable,
          bucketSpec = bucketSpec,
          format,
          caseInsensitiveOptions)(sparkSession)
{% endhighlight %}

There is a [jira ticket](https://issues.apache.org/jira/browse/SPARK-10848) where this topic was discussed. This logic has sense when you need to work with CSV file and there is no way to predict whether the field is nullable or not.

## Workaround

Idea: get correct schema from one of avro files and then recreate dataframe based on correct schema.

{% highlight scala %}
val avroSchema = getSchema(avroFiles.head, spark)
val dfWithOptionalFields = readDF(spark, avroFiles)
val dfWithCorrectFields = dfWithOptionalFields.sqlContext.createDataFrame(dfWithOptionalFields.rdd, avroSchema)
{% endhighlight %}


text:
import UserService from 'torii-user-service/services/user-service';

export default UserService.extend({
  debug: true,
  // customize these in your own app
  authServer: 'http://localhost:3000',
  authenticatioPathl: 'users/me',
  loginPath: 'users/sign_in',
  logoutPath: 'users/sign_out',
  registrationPath: 'users'
});


text:
package io.github.resilience4j.circularbuffer.concurrent;

import org.openjdk.jcstress.annotations.Actor;
import org.openjdk.jcstress.annotations.Arbiter;
import org.openjdk.jcstress.annotations.Expect;
import org.openjdk.jcstress.annotations.JCStressTest;
import org.openjdk.jcstress.annotations.Outcome;
import org.openjdk.jcstress.annotations.State;
import org.openjdk.jcstress.infra.results.StringResult2;

import io.github.resilience4j.circularbuffer.ConcurrentEvictingQueue;

@JCStressTest
@State
@Outcome(id="1, null", expect = Expect.ACCEPTABLE)
@Outcome(id="null, 1", expect = Expect.ACCEPTABLE)
@Outcome(id="null, null", expect = Expect.FORBIDDEN)
@Outcome(id="1, 1", expect = Expect.FORBIDDEN)
public class ConcurrentEvictingQueueDoubleReadTest {

    ConcurrentEvictingQueue<Integer> queue;
    private Integer first;
    private Integer second;

    public ConcurrentEvictingQueueDoubleReadTest() {
        queue = new ConcurrentEvictingQueue<>(2);
        queue.offer(1);
    }

    @Actor
    public void firstActor() {
        first = queue.poll();
    }

    @Actor
    public void secondActor() {
        second = queue.poll();
    }

    @Arbiter
    public void arbiter(StringResult2 result2) {
        result2.r1 = first == null ? "null" : String.valueOf(first);
        result2.r2 = second == null ? "null" : String.valueOf(second);
    }
}


text:
> Provides convenient utility methods for working with Enums and their user-friendly descriptions.

## How to Use

Install via [nuget](https://www.nuget.org/packages/Archon.Enums/)

```
install-package Archon.Enums
```

Make sure to add `using Archon.Enums;` to the top of your files to get access to the following extension methods.

### Categories & Descriptions

Given an `enum` that looks like this:

```c#
enum Color
{
	[Category("Blues")]
	[Description("Alice's Wonderland Blue")]
	AliceBlue,

	GhostWhite,

	[Category("Blues")]
	Navy
}
```

You can now easily retrieve the descriptions and categories for an enum:

```c#
Assert.Equal("Alice's Wonderland Blue", Color.AliceBlue.DescriptionOf());
Assert.Equal("Blues", Color.AliceBlue.CategoryOf());
```

as well as get sensible defaults for non-defined descriptions:

```c#
Assert.Equal("Ghost White", Color.GhostWhite.DescriptionOf());
```

You can also list out the descriptors for the `enum`:

```c#
IEnumerable<EnumDescriptor> values = EnumUtility.Describe(typeof(Color));
foreach (var val in values)
{
	Console.WriteLine(String.Format("{0}: {1} ({2})", val.Category, val.Description, val.Value));
	//this will output "Blues: Alice's Wonderland Blue (AliceBlue)" for Color.AliceBlue
}
```

### States/Provinces & Countries

Install the [geography nuget package](https://www.nuget.org/packages/Archon.Enums.Geography/)

```
install-package Archon.Enums.Geography
```

This includes two enum types, `StateProvince` and `Country` which enumerate US states, Canadian provinces, and countries utilizing the aforementioned framework with user friendly descriptions & categories.


text:
<?php
if (!defined('YOUCANINCLUDE'))
    exit('No direct script access allowed');

if ($_SESSION['IDUSER_ADMIN']) {
    createcssfile();
    $js_compressionx = SITE_LINK . "cache/1" . get_cache('jshash1') . ".js";
} else {
    $js_compressionx = SITE_LINK . "cache/2" . get_cache('jshash2') . ".js";
}

$css_compression = SITE_LINK . "cache/" . get_cache('csshash') . ".css";


text:
var PurpleMine = PurpleMine || {};

PurpleMine.MenuCollapse = (function()
{
    "use strict";

    var self;
    var translations = {
        en: {
            topMenuToggler : "Expand/collapse top menu"
        },
        pl: {
            topMenuToggler : "Zwiń/rozwiń górne menu"
        }
    };

    function MenuCollapse()
    {
        if (self)
        {
            return self;
        }

        self = this;

        this.lang = document.documentElement.lang;

        if (typeof translations[this.lang] === "undefined")
        {
            this.lang = "en";
        }

        this._ = translations[this.lang];

        this.menus = {
            top: {
                $el: $("#top-menu")
            }
        };

        for (var menu in this.menus)
        {
            if (this.menus.hasOwnProperty(menu) &&
                this.menus[menu].$el.length > 0)
            {
                handleMenu(menu);
            }
        }
    }

    function handleMenu(menu)
    {
        if ("none" === self.menus[menu].$el.css("maxHeight"))
        {
            return false;
        }

        self.menus[menu].collapsed = true;

        if (window.localStorage)
        {
            self.menus[menu].collapsed =
                null === localStorage.getItem(getMenuStorageKey(menu));
        }

        buildToggleButton(menu);

        if (false === self.isCollapsed(menu))
        {
            self.expandMenu(menu);
        }
    }

    function getMenuStorageKey(menu)
    {
        return "PurpleMine:" + menu + "MenuExpanded";
    }

    function buildToggleButton(menu)
    {
        var togglerClass = menu + "-menu-toggler",
            togglerLabel = self._[menu + "MenuToggler"],
            togglerHtml;

        togglerHtml = "";
        self.menus[menu].$toggler = $(togglerHtml);

        self.menus[menu].$el.prepend(self.menus[menu].$toggler);
        self.menus[menu].$toggler.on("click", { menu: menu }, self.toggleMenu);
    }

    MenuCollapse.prototype.toggleMenu = function(event)
    {
        var menu = event.data.menu || "";

        if (self.isCollapsed(menu))
        {
            self.expandMenu(menu);
        }
        else
        {
            self.collapseMenu(menu);
        }
    };

    MenuCollapse.prototype.isCollapsed = function(menu)
    {
        return this.menus[menu].collapsed;
    };

    MenuCollapse.prototype.expandMenu = function(menu)
    {
        this.menus[menu].$el.addClass("expanded");
        this.menus[menu].$toggler.addClass("expanded");
        this.menus[menu].collapsed = false;

        if (window.localStorage)
        {
            localStorage.setItem(getMenuStorageKey(menu), "x");
        }
    };

    MenuCollapse.prototype.collapseMenu = function(menu)
    {
        this.menus[menu].$el.removeClass("expanded");
        this.menus[menu].$toggler.removeClass("expanded");
        this.menus[menu].collapsed = true;

        if (window.localStorage)
        {
            localStorage.removeItem(getMenuStorageKey(menu));
        }
    };

    return MenuCollapse;
}());


text:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.broad.igv.sam.reader;

import org.broad.igv.util.collections.SortingCollection;
import org.broad.igv.util.collections.SortingCollection.Codec;
import org.broad.igv.logging.*;
import org.broad.igv.sam.DotAlignedAlignment;

import java.io.*;

/**
 * private String chromosome;
 * private int start;
 * private int end;
 * boolean negativeStrand;
 *
 * @author jrobinso
 */
public class DotAlignedCodec implements SortingCollection.Codec<DotAlignedAlignment> {

    private static Logger log = LogManager.getLogger(DotAlignedCodec.class);
    DataOutputStream outputStream;
    DataInputStream inputStream;

    public void setOutputStream(OutputStream outputStream) {
        this.outputStream = new DataOutputStream(outputStream);
    }

    public void setInputStream(InputStream inputStream) {
        this.inputStream = new DataInputStream(inputStream);
    }

    public void encode(DotAlignedAlignment alignment) {
        try {
            outputStream.writeUTF(alignment.getChr());
            outputStream.writeInt(alignment.getStart());
            outputStream.writeInt(alignment.getEnd());
            outputStream.writeBoolean(alignment.isNegativeStrand());
        } catch (IOException ex) {
            log.error("Error encoding alignment", ex);
        }
    }

    public DotAlignedAlignment decode() {
        try {

            String chr = inputStream.readUTF();
            int start = inputStream.readInt();
            int end = inputStream.readInt();
            boolean negativeStrand = inputStream.readBoolean();
            return new DotAlignedAlignment(chr, start, end, negativeStrand);
        } catch (EOFException ex) {
            return null;
        } catch (IOException ex) {
            log.error("Error decoding alignment", ex);
            return null;
        }
    }

    public Codec<DotAlignedAlignment> clone() {
        DotAlignedCodec other = new DotAlignedCodec();
        return other;
    }
}


text:
package com.netflix.ribbon.proxy;

import org.junit.Test;

import java.io.InputStream;
import java.lang.reflect.Method;

import static junit.framework.Assert.*;

/**
 * @author Tomasz Bak
 */
public class UtilsTest {

    @Test
    public void testMethodByName() throws Exception {
        Method source = Utils.methodByName(String.class, "equals");
        assertNotNull(source);
        assertEquals("equals", source.getName());

        assertNull(Utils.methodByName(String.class, "not_equals"));
    }

    @Test
    public void testExecuteOnInstance() throws Exception {
        Method source = Utils.methodByName(String.class, "equals");
        Object obj = new Object();
        assertEquals(Boolean.TRUE, Utils.executeOnInstance(obj, source, new Object[]{obj}));
        assertEquals(Boolean.FALSE, Utils.executeOnInstance(obj, source, new Object[]{this}));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testExecuteNotExistingMethod() throws Exception {
        Method source = Utils.methodByName(String.class, "getChars");
        Utils.executeOnInstance(new Object(), source, new Object[]{});
    }

    @Test
    public void testNewInstance() throws Exception {
        assertNotNull(Utils.newInstance(Object.class));
    }

    @Test(expected = RibbonProxyException.class)
    public void testNewInstanceForFailure() throws Exception {
        Utils.newInstance(InputStream.class);
    }
}


text:
/**
 *
 * magmawinthread.h
 *
 *  This file handles the mapping from pthreads calls to windows threads.
 *  MAGMA is a software package provided by Univ. of Tennessee,
 *  Univ. of California Berkeley and Univ. of Colorado Denver
 *
 * @version 2.3.1
 * @author Piotr Luszczek
 * @date July 2014
 *
 * This file is originally from PLASMA project, where plasma has been
 * replaced by MAGMA.
 *
 **/
#ifndef MAGMAWINTHREAD_H
#define MAGMAWINTHREAD_H

#if defined( _WIN32 ) || defined( _WIN64 )

#include <windows.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct pthread_s {
  HANDLE hThread;
  unsigned int uThId;
} pthread_t;

typedef HANDLE pthread_mutex_t;
typedef int pthread_mutexattr_t;
typedef int pthread_attr_t;
typedef int pthread_condattr_t;

typedef struct pthread_cond_s {
  HANDLE hSem;
  HANDLE hEvt;
  CRITICAL_SECTION cs;
  int waitCount; /* waiting thread counter */
} pthread_cond_t;

typedef int pthread_attr_t;

#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1)

#define PTHREAD_SCOPE_SYSTEM 1

#define MAGMA_DLLPORT
#define MAGMA_CDECL __cdecl

MAGMA_DLLPORT pthread_t MAGMA_CDECL pthread_self(void);
MAGMA_DLLPORT int MAGMA_CDECL pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t * attr);
MAGMA_DLLPORT int MAGMA_CDECL pthread_mutex_destroy(pthread_mutex_t *mutex);
MAGMA_DLLPORT int MAGMA_CDECL pthread_mutex_lock(pthread_mutex_t *mutex);
MAGMA_DLLPORT int MAGMA_CDECL pthread_mutex_trylock(pthread_mutex_t *mutex);
MAGMA_DLLPORT int MAGMA_CDECL pthread_mutex_unlock(pthread_mutex_t *mutex);
MAGMA_DLLPORT int MAGMA_CDECL pthread_attr_init(pthread_attr_t *attr);
MAGMA_DLLPORT int MAGMA_CDECL pthread_attr_destroy(pthread_attr_t *attr);
MAGMA_DLLPORT int MAGMA_CDECL pthread_attr_setscope(pthread_attr_t *attr, int scope);
MAGMA_DLLPORT int MAGMA_CDECL pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start) (void *), void *arg);
MAGMA_DLLPORT int MAGMA_CDECL pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
MAGMA_DLLPORT int MAGMA_CDECL pthread_cond_destroy(pthread_cond_t *cond);
MAGMA_DLLPORT int MAGMA_CDECL pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
MAGMA_DLLPORT int MAGMA_CDECL pthread_cond_broadcast(pthread_cond_t *cond);
MAGMA_DLLPORT int MAGMA_CDECL pthread_join(pthread_t thread, void **value_ptr);
MAGMA_DLLPORT int MAGMA_CDECL pthread_equal(pthread_t thread1, pthread_t thread2);

MAGMA_DLLPORT int MAGMA_CDECL pthread_setconcurrency (int);

MAGMA_DLLPORT unsigned int MAGMA_CDECL pthread_self_id(void);

#ifdef __cplusplus
}
#endif

#endif /* defined( _WIN32 ) || defined( _WIN64 ) */

#endif /* MAGMAWINTHREAD_H */


text:
using GenFx.Components.Plugins;
using GenFx.Validation;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using TestCommon;
using TestCommon.Mocks;
using Xunit;

namespace GenFx.Components.Tests
{
    /// <summary>
    /// Contains unit tests for the <see cref="MetricLogger"/> class.
    /// </summary>
    public class MetricLoggerTest : IDisposable
    {
        private readonly TestTraceListener traceListener;

        public MetricLoggerTest()
        {
            this.traceListener = new TestTraceListener();
            Trace.Listeners.Add(this.traceListener);
        }

        public void Dispose()
        {
            Trace.Listeners.Remove(this.traceListener);
        }

        /// <summary>
        /// Tests that the <see cref="MetricLogger"/> can be validated successfully.
        /// </summary>
        [Fact]
        public void MetricLogger_Validation()
        {
            MetricLogger logger = new MetricLogger
            {
                TraceCategory = "test"
            };

            logger.Validate();
        }

        /// <summary>
        /// Tests that validation fails when no value is provided for <see cref="MetricLogger.TraceCategory"/>.
        /// </summary>
        [Fact]
        public void MetricLogger_Validation_MissingTraceCategory()
        {
            MetricLogger logger = new MetricLogger();
            Assert.Throws<ValidationException>(() => logger.Validate());
        }

        /// <summary>
        /// Tests that the <see cref="MetricLogger.OnAlgorithmStarting"/> method works correctly.
        /// </summary>
        [Fact]
        public void MetricLogger_AlgorithmStarting()
        {
            MetricLogger logger = new MetricLogger
            {
                TraceCategory = "test"
            };

            Assert.Equal(String.Empty, this.traceListener.Output.ToString());

            PrivateObject accessor = new PrivateObject(logger);
            accessor.Invoke("OnAlgorithmStarting");

            Assert.StartsWith(logger.TraceCategory, this.traceListener.Output.ToString());
            Assert.Contains(Resources.MetricLogger_AlgorithmStarted, this.traceListener.Output.ToString());
        }

        /// <summary>
        /// Tests that the <see cref="MetricLogger.OnAlgorithmCompleted"/> method works correctly.
        /// </summary>
        [Fact]
        public void MetricLogger_AlgorithmCompleted()
        {
            MetricLogger logger = new MetricLogger
            {
                TraceCategory = "test"
            };

            Assert.Equal(String.Empty, this.traceListener.Output.ToString());

            PrivateObject accessor = new PrivateObject(logger);
            accessor.Invoke("OnAlgorithmCompleted");

            Assert.StartsWith(logger.TraceCategory, this.traceListener.Output.ToString());
            Assert.Contains(Resources.MetricLogger_AlgorithmCompleted, this.traceListener.Output.ToString());
        }

        /// <summary>
        /// Tests that the <see cref="MetricLogger.OnFitnessEvaluated"/> method works correctly.
        /// </summary>
        [Fact]
        public void MetricLogger_FitnessEvaluated()
        {
            MockGeneticAlgorithm algorithm = new MockGeneticAlgorithm();
            algorithm.Metrics.Add(new TestMetric1());
            algorithm.Metrics.Add(new TestMetric2());
            algorithm.Metrics.Add(new TestMetric3());

            MetricLogger logger = new MetricLogger
            {
                TraceCategory = "test"
            };
            logger.Initialize(algorithm);

            Assert.Equal(String.Empty, this.traceListener.Output.ToString());

            GeneticEnvironment environment = new GeneticEnvironment(algorithm);
            environment.Populations.Add(new MockPopulation { Index = 0 });
            environment.Populations.Add(new MockPopulation { Index = 1 });

            PrivateObject accessor = new PrivateObject(logger);
            accessor.Invoke("OnFitnessEvaluated", environment, 0);

            string[] lines = this.traceListener.Output.ToString().Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
            Assert.Equal(24, lines.Length);
            this.VerifyMetricOutput(lines.Take(4).ToArray(), logger.TraceCategory, "Metric 1", "1:0", 0, 0);
            this.VerifyMetricOutput(lines.Skip(4).Take(4).ToArray(), logger.TraceCategory, "Metric 2", "2:0", 0, 0);
            this.VerifyMetricOutput(lines.Skip(8).Take(4).ToArray(), logger.TraceCategory, typeof(TestMetric3).FullName, "3:0", 0, 0);
            this.VerifyMetricOutput(lines.Skip(12).Take(4).ToArray(), logger.TraceCategory, "Metric 1", "1:1", 1, 0);
            this.VerifyMetricOutput(lines.Skip(16).Take(4).ToArray(), logger.TraceCategory, "Metric 2", "2:1", 1, 0);
            this.VerifyMetricOutput(lines.Skip(20).Take(4).ToArray(), logger.TraceCategory, typeof(TestMetric3).FullName, "3:1", 1, 0);
        }

        /// <summary>
        /// Tests that an exception is thrown when passing a null environment to <see cref="MetricLogger.OnFitnessEvaluated"/>.
        /// </summary>
        [Fact]
        public void MetricLogger_OnFitnessEvaluated_NullEnvironment()
        {
            MetricLogger logger = new MetricLogger();
            PrivateObject accessor = new PrivateObject(logger);
            Assert.Throws<ArgumentNullException>(() => accessor.Invoke("OnFitnessEvaluated", null, 0));
        }

        private void VerifyMetricOutput(string[] metricOutput, string traceCategory, string metricName, string metricValue, int populationIndex, int generationIndex)
        {
            Assert.StartsWith(traceCategory, metricOutput[0]);
            Assert.Contains("Metric Name: " + metricName, metricOutput[0]);
            Assert.Equal("Metric Value: " + metricValue, metricOutput[1]);
            Assert.Equal("Population Index: " + populationIndex, metricOutput[2]);
            Assert.Equal("Generation Index: " + generationIndex, metricOutput[3]);
        }

        private class TestTraceListener : TraceListener
        {
            public StringBuilder Output = new StringBuilder();

            public override void Write(string message)
            {
                this.Output.Append(message);
            }

            public override void WriteLine(string message)
            {
                this.Output.AppendLine(message);
            }
        }

        [DisplayName("Metric 1")]
        private class TestMetric1 : Metric
        {
            public override object GetResultValue(Population population)
            {
                return "1:" + population.Index;
            }
        }

        private class TestMetric2 : Metric
        {
            public override object GetResultValue(Population population)
            {
                return "2:" + population.Index;
            }

            public override string ToString()
            {
                return "Metric 2";
            }
        }

        [DisplayName]
        private class TestMetric3 : Metric
        {
            public override object GetResultValue(Population population)
            {
                return "3:" + population.Index;
            }
        }
    }
}


text:
require 'cucumber-api/response'
require 'rest-client'
require 'json'
require 'jsonpath'
require 'minitest'

Given(/^I sign in to keycloak with "([^"]*)" and "([^"]*)"$/) do |username, password|
  realm = 'havendev'
  auth_server = ENV['AUTH_SERVER'] || 'dev.havengrc.com'
  request_url = "http://#{auth_server}/auth/realms/#{realm}/protocol/openid-connect/token"
  body = {
    'grant_type' => 'password',
    'client_id'  => realm,
    'username'   => username,
    'password'   => password
  }
  headers = {}
  response = RestClient.post request_url, body, headers
  access_token = JSON.parse(response)["access_token"]
  @headers = {} if @headers.nil?
  @headers['Authorization'] = "Bearer #{access_token}"
end

Given(/^I wait for (\d+) seconds?$/) do |n|
  sleep(n.to_i)
end

Then(/^all "([^"]*)" fields should be of type (numeric|string|boolean|numeric_string) and value "([^"]*)"$/) do |field, type, value|
  raise 'No response found.' if @response.nil?
  json = JSON.parse @response.body
  fields = JsonPath.new("$..#{field}").on(json)
  # puts "we got #{fields.length} fields back"
  # puts fields
  fields.each do |f|
    case type
    when 'numeric'
      assert f.is_a? Numeric
    when 'array'
      assert f.is_a? Array
    when 'string'
      assert f.is_a? String
    when 'boolean'
      assert !!f == f # rubocop:disable Style/DoubleNegation
    when 'numeric_string'
      assertf.is_a?(Numeric) or f.is_a?(String)
    when 'object'
      assert f.is_a? Hash
    else
      raise %/Invalid expected type '#{type}'/
    end
    assert_equal value, f
  end

end


text:
package org.fedorahosted.freeotp.dialogs;

import org.fedorahosted.freeotp.R;
import org.fedorahosted.freeotp.Token.TokenUriInvalidException;
import org.fedorahosted.freeotp.TokenPersistence;

import android.widget.Toast;

public abstract class BaseAddTokenDialogActivity extends BaseDialogActivity {
    public BaseAddTokenDialogActivity(int layout, int negative, int neutral, int positive) {
        super(layout, negative, neutral, positive);
    }

    protected void onTokenURI(String uri) {
        try {
            if (uri != null)
                new TokenPersistence(this).add(uri);
        } catch (TokenUriInvalidException e) {
            Toast.makeText(this, R.string.invalid_token, Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
    }
}


text:
package com.linkedin.pinot.core.query.executor;

import com.google.common.base.Preconditions;
import com.linkedin.pinot.common.exception.QueryException;
import com.linkedin.pinot.common.metrics.ServerMeter;
import com.linkedin.pinot.common.metrics.ServerMetrics;
import com.linkedin.pinot.common.metrics.ServerQueryPhase;
import com.linkedin.pinot.common.request.BrokerRequest;
import com.linkedin.pinot.common.utils.CommonConstants;
import com.linkedin.pinot.common.utils.DataTable;
import com.linkedin.pinot.core.common.datatable.DataTableBuilder;
import com.linkedin.pinot.core.common.datatable.DataTableImplV2;
import com.linkedin.pinot.core.data.manager.InstanceDataManager;
import com.linkedin.pinot.core.data.manager.SegmentDataManager;
import com.linkedin.pinot.core.data.manager.TableDataManager;
import com.linkedin.pinot.core.indexsegment.IndexSegment;
import com.linkedin.pinot.core.plan.Plan;
import com.linkedin.pinot.core.plan.maker.InstancePlanMakerImplV2;
import com.linkedin.pinot.core.plan.maker.PlanMaker;
import com.linkedin.pinot.core.query.config.QueryExecutorConfig;
import com.linkedin.pinot.core.query.exception.BadQueryRequestException;
import com.linkedin.pinot.core.query.pruner.SegmentPrunerService;
import com.linkedin.pinot.core.query.request.ServerQueryRequest;
import com.linkedin.pinot.core.query.request.context.TimerContext;
import com.linkedin.pinot.core.util.trace.TraceContext;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import javax.annotation.concurrent.ThreadSafe;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ThreadSafe
public class ServerQueryExecutorV1Impl implements QueryExecutor {
  private static final Logger LOGGER = LoggerFactory.getLogger(ServerQueryExecutorV1Impl.class);
  private static final boolean PRINT_QUERY_PLAN = false;

  private InstanceDataManager _instanceDataManager = null;
  private SegmentPrunerService _segmentPrunerService = null;
  private PlanMaker _planMaker = null;
  private long _defaultTimeOutMs = CommonConstants.Server.DEFAULT_QUERY_EXECUTOR_TIMEOUT_MS;
  private final Map<String, Long> _tableTimeoutMs = new ConcurrentHashMap<>();
  private ServerMetrics _serverMetrics;

  @Override
  public synchronized void init(Configuration config, InstanceDataManager instanceDataManager,
      ServerMetrics serverMetrics) throws ConfigurationException {
    _instanceDataManager = instanceDataManager;
    _serverMetrics = serverMetrics;
    QueryExecutorConfig queryExecutorConfig = new QueryExecutorConfig(config);
    if (queryExecutorConfig.getTimeOut() > 0) {
      _defaultTimeOutMs = queryExecutorConfig.getTimeOut();
    }
    LOGGER.info("Default timeout for query executor : {}", _defaultTimeOutMs);
    LOGGER.info("Trying to build SegmentPrunerService");
    _segmentPrunerService = new SegmentPrunerService(queryExecutorConfig.getPrunerConfig());
    LOGGER.info("Trying to build QueryPlanMaker");
    _planMaker = new InstancePlanMakerImplV2(queryExecutorConfig);
    LOGGER.info("Trying to build QueryExecutorTimer");
  }

  @Override
  public synchronized void start() {
    LOGGER.info("Query executor started");
  }

  @Override
  public synchronized void shutDown() {
    LOGGER.info("Query executor shut down");
  }

  @Override
  public DataTable processQuery(ServerQueryRequest queryRequest, ExecutorService executorService) {
    TimerContext timerContext = queryRequest.getTimerContext();
    TimerContext.Timer schedulerWaitTimer = timerContext.getPhaseTimer(ServerQueryPhase.SCHEDULER_WAIT);
    if (schedulerWaitTimer != null) {
      schedulerWaitTimer.stopAndRecord();
    }
    long querySchedulingTimeMs = System.currentTimeMillis() - timerContext.getQueryArrivalTimeMs();
    TimerContext.Timer queryProcessingTimer = timerContext.startNewPhaseTimer(ServerQueryPhase.QUERY_PROCESSING);

    long requestId = queryRequest.getRequestId();
    BrokerRequest brokerRequest = queryRequest.getBrokerRequest();
    LOGGER.debug("Incoming request Id: {}, query: {}", requestId, brokerRequest);
    String tableNameWithType = queryRequest.getTableNameWithType();
    long queryTimeoutMs = _tableTimeoutMs.getOrDefault(tableNameWithType, _defaultTimeOutMs);
    long remainingTimeMs = queryTimeoutMs - querySchedulingTimeMs;

    // Query scheduler wait time already exceeds query timeout, directly return
    if (remainingTimeMs <= 0) {
      _serverMetrics.addMeteredQueryValue(brokerRequest, ServerMeter.SCHEDULING_TIMEOUT_EXCEPTIONS, 1);
      String errorMessage =
          String.format("Query scheduling took %dms (longer than query timeout of %dms)", querySchedulingTimeMs,
              queryTimeoutMs);
      DataTable dataTable = new DataTableImplV2();
      dataTable.addException(QueryException.getException(QueryException.QUERY_SCHEDULING_TIMEOUT_ERROR, errorMessage));
      LOGGER.error("{} while processing requestId: {}", errorMessage, requestId);
      return dataTable;
    }

    TableDataManager tableDataManager = _instanceDataManager.getTableDataManager(tableNameWithType);
    Preconditions.checkState(tableDataManager != null, "Failed to find data manager for table: " + tableNameWithType);
    List<SegmentDataManager> segmentDataManagers = tableDataManager.acquireSegments(queryRequest.getSegmentsToQuery());
    boolean enableTrace = queryRequest.isEnableTrace();
    if (enableTrace) {
      TraceContext.register(requestId);
    }

    DataTable dataTable = null;
    try {
      TimerContext.Timer segmentPruneTimer = timerContext.startNewPhaseTimer(ServerQueryPhase.SEGMENT_PRUNING);
      long totalRawDocs = pruneSegments(tableDataManager, segmentDataManagers, queryRequest);
      segmentPruneTimer.stopAndRecord();

      int numSegmentsMatched = segmentDataManagers.size();
      queryRequest.setSegmentCountAfterPruning(numSegmentsMatched);
      LOGGER.debug("Matched {} segments", numSegmentsMatched);
      if (numSegmentsMatched == 0) {
        dataTable = DataTableBuilder.buildEmptyDataTable(brokerRequest);
        Map<String, String> metadata = dataTable.getMetadata();
        metadata.put(DataTable.TOTAL_DOCS_METADATA_KEY, String.valueOf(totalRawDocs));
        metadata.put(DataTable.NUM_DOCS_SCANNED_METADATA_KEY, "0");
        metadata.put(DataTable.NUM_ENTRIES_SCANNED_IN_FILTER_METADATA_KEY, "0");
        metadata.put(DataTable.NUM_ENTRIES_SCANNED_POST_FILTER_METADATA_KEY, "0");
      } else {
        TimerContext.Timer planBuildTimer = timerContext.startNewPhaseTimer(ServerQueryPhase.BUILD_QUERY_PLAN);
        Plan globalQueryPlan =
            _planMaker.makeInterSegmentPlan(segmentDataManagers, brokerRequest, executorService, remainingTimeMs);
        planBuildTimer.stopAndRecord();

        if (PRINT_QUERY_PLAN) {
          LOGGER.debug("***************************** Query Plan for Request {} ***********************************",
              queryRequest.getRequestId());
          globalQueryPlan.print();
          LOGGER.debug("*********************************** End Query Plan ***********************************");
        }

        TimerContext.Timer planExecTimer = timerContext.startNewPhaseTimer(ServerQueryPhase.QUERY_PLAN_EXECUTION);
        dataTable = globalQueryPlan.execute();
        planExecTimer.stopAndRecord();

        // Update the total docs in the metadata based on un-pruned segments.
        dataTable.getMetadata().put(DataTable.TOTAL_DOCS_METADATA_KEY, Long.toString(totalRawDocs));
      }
    } catch (Exception e) {
      _serverMetrics.addMeteredQueryValue(brokerRequest, ServerMeter.QUERY_EXECUTION_EXCEPTIONS, 1);

      // Do not log error for BadQueryRequestException because it's caused by bad query
      if (e instanceof BadQueryRequestException) {
        LOGGER.info("Caught BadQueryRequestException while processing requestId: {}, {}", requestId, e.getMessage());
      } else {
        LOGGER.error("Exception processing requestId {}", requestId, e);
      }

      dataTable = new DataTableImplV2();
      dataTable.addException(QueryException.getException(QueryException.QUERY_EXECUTION_ERROR, e));
    } finally {
      for (SegmentDataManager segmentDataManager : segmentDataManagers) {
        tableDataManager.releaseSegment(segmentDataManager);
      }
      if (enableTrace) {
        if (dataTable != null) {
          dataTable.getMetadata().put(DataTable.TRACE_INFO_METADATA_KEY, TraceContext.getTraceInfo());
        }
        TraceContext.unregister();
      }
    }

    queryProcessingTimer.stopAndRecord();
    long queryProcessingTime = queryProcessingTimer.getDurationMs();
    dataTable.getMetadata().put(DataTable.TIME_USED_MS_METADATA_KEY, Long.toString(queryProcessingTime));
    LOGGER.debug("Query processing time for request Id - {}: {}", requestId, queryProcessingTime);
    LOGGER.debug("InstanceResponse for request Id - {}: {}", requestId, dataTable);
    return dataTable;
  }

  /**
   * Helper method to prune segments.
   *
   * @param tableDataManager Table data manager
   * @param segmentDataManagers List of segments to prune
   * @param serverQueryRequest Server query request
   * @return Total number of docs across all segments (including the ones that were pruned).
   */
  private long pruneSegments(TableDataManager tableDataManager, List<SegmentDataManager> segmentDataManagers,
      ServerQueryRequest serverQueryRequest) {
    long totalRawDocs = 0;

    Iterator<SegmentDataManager> iterator = segmentDataManagers.iterator();
    while (iterator.hasNext()) {
      SegmentDataManager segmentDataManager = iterator.next();
      IndexSegment indexSegment = segmentDataManager.getSegment();
      // We need to compute the total raw docs for the table before any pruning.
      totalRawDocs += indexSegment.getSegmentMetadata().getTotalRawDocs();
      if (_segmentPrunerService.prune(indexSegment, serverQueryRequest)) {
        iterator.remove();
        tableDataManager.releaseSegment(segmentDataManager);
      }
    }

    return totalRawDocs;
  }

  @Override
  public void setTableTimeoutMs(String tableNameWithType, long timeOutMs) {
    _tableTimeoutMs.put(tableNameWithType, timeOutMs);
  }
}


text:
<?php

namespace Multiservices\InventarioBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * ArticulosDetalleClienteHistorial
 */
class ArticulosDetalleClienteHistorial
{
    /**
     * @var integer
     */
    private $id;

    /**
     * @var integer
     */
    private $codusuario;

    /**
     * @var integer
     */
    private $codarticulodetalle;

    /**
     * @var \DateTime
     */
    private $fecha;

    /**
     * @var string
     */
    private $tipo;
    /**
     * @var string
     */
    private $observacion;

     public function __construct() {

         $this->fecha = new \DateTime();
     }
    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set codusuario
     *
     * @param integer $codusuario
     * @return ArticulosDetalleClienteHistorial
     */
    public function setCodusuario($codusuario)
    {
        $this->codusuario = $codusuario;

        return $this;
    }

    /**
     * Get codusuario
     *
     * @return integer
     */
    public function getCodusuario()
    {
        return $this->codusuario;
    }

    /**
     * Set codarticulodetalle
     *
     * @param integer $codarticulodetalle
     * @return ArticulosDetalleClienteHistorial
     */
    public function setCodarticulodetalle($codarticulodetalle)
    {
        $this->codarticulodetalle = $codarticulodetalle;

        return $this;
    }

    /**
     * Get codarticulodetalle
     *
     * @return integer
     */
    public function getCodarticulodetalle()
    {
        return $this->codarticulodetalle;
    }

    /**
     * Set fecha
     *
     * @param \DateTime $fecha
     * @return ArticulosDetalleClienteHistorial
     */
    public function setFecha($fecha)
    {
        $this->fecha = $fecha;

        return $this;
    }

    /**
     * Get fecha
     *
     * @return \DateTime
     */
    public function getFecha()
    {
        return $this->fecha;
    }

    /**
     * Set tipo
     *
     * @param string $tipo
     * @return ArticulosDetalleClienteHistorial
     */
    public function setTipo($tipo)
    {
        $this->tipo = $tipo;

        return $this;
    }

    /**
     * Get tipo
     *
     * @return string
     */
    public function getTipo()
    {
        return $this->tipo;
    }
     /**
     * Set observacion
     *
     * @param string $observacion
     * @return ArticulosDetalleClienteHistorial
     */
    public function setObservacion($observacion)
    {
        $this->observacion = $observacion;

        return $this;
    }

    /**
     * Get observacion
     *
     * @return string
     */
    public function getObservacion()
    {
        return $this->observacion;
    }

    public function __toString()
    {
      date_default_timezone_set ("America/Guayaquil");
    return $this->getFecha()->format('Y-m-d H:i:s')." - ".$this->getCodarticulodetalle()." - ".$this->getTipo()." - ".$this->getObservacion();

    }
}


text:
============================
Unsupervised Learning
============================

Core API
--------

References
----------


text:
package model

import (
	"strconv"
)

type VariableType int

const (
	VariableReal VariableType = iota
	VariableInteger
	VariableBinary
	VariableArc
)

func (t VariableType) String() string {
	switch t {
	case VariableReal:
		return "Real"
	case VariableInteger:
		return "Integer"
	case VariableBinary:
		return "Binary"
	case VariableArc:
		return "Arc"
	}
	return "Unknown"
}

type Variable struct {
	Name       string
	Type       VariableType
	LowerBound float64
	UpperBound float64
	Index      int
}

func (v Variable) String() string {
	str := "Name: " + v.Name
	str += " Type: " + v.Type.String()
	str += " Min: " + strconv.FormatFloat(v.LowerBound, 'E', -1, 64)
	str += " Max: " + strconv.FormatFloat(v.UpperBound, 'E', -1, 64)
	return str
}


text:
package April2021Leetcode;

import java.util.HashMap;

public class _0291WordPatternII {

	public static void main(String[] args) {
		System.out.println(wordPatternMatch("abab", "redblueredblue"));
		System.out.println(wordPatternMatch("aaaa", "asdasdasdasd"));
		System.out.println(wordPatternMatch("abab", "asdasdasdasd"));
		System.out.println(wordPatternMatch("aabb", "xyzabcxzyabc"));
		System.out.println(wordPatternMatch("ab", "aa"));
	}

	public static boolean wordPatternMatch(String pattern, String s) {
		HashMap<Character, String> patternMap = new HashMap<Character, String>();
		HashMap<String, Character> sMap = new HashMap<String, Character>();
		return dfs(0, 0, pattern, s, patternMap, sMap);
	}

	public static boolean dfs(int patternIndex, int stringIndex, String pattern, String s,
			HashMap<Character, String> patternMap, HashMap<String, Character> sMap) {

		if (patternIndex == pattern.length() && stringIndex == s.length())
			return true;

		if (patternIndex >= pattern.length() || stringIndex >= s.length())
			return false;

		boolean out = false;
		char c = pattern.charAt(patternIndex);

		String str = "";
		for (int i = stringIndex; i < s.length(); i++) {
			str += s.charAt(stringIndex);

			if (patternMap.containsKey(c)) {
				if (!patternMap.get(c).equals(str)) {
					continue;
				} else {
					if (!sMap.containsKey(str) || sMap.get(str) != c) {
						continue;
					}
					if (dfs(patternIndex + 1, i + 1, pattern, s, patternMap, sMap))
						return true;
				}
			} else {
				if (sMap.containsKey(str)) {
					continue;
				}

				patternMap.put(c, str);
				sMap.put(str, c);

				if (!dfs(patternIndex + 1, i + 1, pattern, s, patternMap, sMap)) {
					patternMap.remove(c);
					sMap.remove(str);
				} else {
					return true;
				}

			}

		}
		return out;
	}

}


text:
<?xml version="1.0" encoding="UTF-8"?>
<results title="frequencies">
 <result title="frequency" count="2">Ae. vexans</result>
 <result title="frequency" count="1">Aedes albopictus</result>
 <result title="frequency" count="1">Ae. aegypti</result>
</results>


text:
typedef NS_ENUM(NSInteger, MXPanGestureDirection) {
    MXPanGestureDirectionNone  = 1 << 0,
    MXPanGestureDirectionRight = 1 << 1,
    MXPanGestureDirectionLeft  = 1 << 2,
    MXPanGestureDirectionUp    = 1 << 3,
    MXPanGestureDirectionDown  = 1 << 4
};

@interface MXScrollView : UIScrollView <UIScrollViewDelegate, UIGestureRecognizerDelegate>
@property (nonatomic, assign) CGFloat minimumHeigth;
@property (nonatomic, strong) MXSegmentedPager *segmentedPager;
@property (nonatomic, strong) MXProgressBlock progressBlock;

@property (nonatomic, strong) NSMutableArray *observedViews;
@end

@implementation MXScrollView {
    BOOL _isObserving;
    BOOL _lock;
}

static void * const kMXScrollViewKVOContext = (void*)&kMXScrollViewKVOContext;
static NSString* const kContentOffsetKeyPath = @"contentOffset";

- (instancetype)init {
    self = [super init];
    if (self) {

        self.delegate = self;
        self.alwaysBounceVertical = NO;
        self.showsVerticalScrollIndicator = NO;
        self.directionalLockEnabled = YES;
        self.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
        self.contentMode = UIViewContentModeTopRight;

        self.observedViews = [NSMutableArray array];

        self.minimumHeigth = 0;
        [self addObserver:self forKeyPath:kContentOffsetKeyPath
                  options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld
                  context:kMXScrollViewKVOContext];
    }
    return self;
}

#pragma mark <UIScrollViewDelegate>

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

    if ((self.contentOffset.y >= -self.minimumHeigth)) {
        self.contentOffset = CGPointMake(self.contentOffset.x, -self.minimumHeigth);
    }

    [scrollView shouldPositionParallaxHeader];

    if (self.progressBlock) {
        self.progressBlock(scrollView.parallaxHeader.progress);
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    _lock = NO;
    [self removeObservedViews];
}

#pragma mark <UIGestureRecognizerDelegate>

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{

    if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
        MXPanGestureDirection direction = [self getDirectionOfPanGestureRecognizer:(UIPanGestureRecognizer*)gestureRecognizer];

        if (direction == MXPanGestureDirectionLeft || direction == MXPanGestureDirectionRight) {
            return NO;
        }
    }
    return YES;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {

    UIView<MXPageProtocol> *page = (id) self.segmentedPager.pager.selectedPage;
    BOOL shouldScroll = YES;

    if ([page respondsToSelector:@selector(segmentedPager:shouldScrollWithView:)]) {
        shouldScroll = [page segmentedPager:self.segmentedPager shouldScrollWithView:otherGestureRecognizer.view];
    }

    if (shouldScroll) {
        [self addObservedView:otherGestureRecognizer.view];
    }
    return shouldScroll;
}

- (MXPanGestureDirection) getDirectionOfPanGestureRecognizer:(UIPanGestureRecognizer*) panGestureRecognizer {

    CGPoint velocity = [panGestureRecognizer velocityInView:self];
    CGFloat absX = fabs(velocity.x);
    CGFloat absY = fabs(velocity.y);

    if (absX > absY) {
        return (velocity.x > 0)? MXPanGestureDirectionRight : MXPanGestureDirectionLeft;
    }
    else if (absX < absY) {
        return (velocity.y > 0)? MXPanGestureDirectionDown : MXPanGestureDirectionUp;
    }
    return MXPanGestureDirectionNone;
}

#pragma mark KVO

- (void) addObserverToView:(UIView *)view {
    _isObserving = NO;
    if ([view isKindOfClass:[UIScrollView class]]) {
        [view addObserver:self
               forKeyPath:kContentOffsetKeyPath
                  options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew
                  context:kMXScrollViewKVOContext];
    }
    _isObserving = YES;
}

- (void) removeObserverFromView:(UIView *)view {
    @try {
        if ([view isKindOfClass:[UIScrollView class]]) {
            [view removeObserver:self
                      forKeyPath:kContentOffsetKeyPath
                         context:kMXScrollViewKVOContext];
        }
    }
    @catch (NSException *exception) {}
}

//This is where the magic happens...
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    if (context == kMXScrollViewKVOContext && [keyPath isEqualToString:kContentOffsetKeyPath]) {

        CGPoint new = [[change objectForKey:NSKeyValueChangeNewKey] CGPointValue];
        CGPoint old = [[change objectForKey:NSKeyValueChangeOldKey] CGPointValue];

        if (old.y == new.y) return;

        if (_isObserving && object == self) {
            //Adjust self scroll offset
            if ((old.y - new.y) > 0 && _lock) {
                [self scrollView:self setContentOffset:old];
            }
        }
        else if (_isObserving && [object isKindOfClass:[UIScrollView class]]) {

            //Adjust the observed scrollview's content offset
            UIScrollView *scrollView = object;
            _lock = !(scrollView.contentOffset.y <= -scrollView.contentInset.top);

            //Manage scroll up
            if (self.contentOffset.y < -self.minimumHeigth && _lock && (old.y - new.y) < 0) {
                [self scrollView:scrollView setContentOffset:old];
            }
            //Disable bouncing when scroll down
            if (!_lock) {
                [self scrollView:scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, -scrollView.contentInset.top)];
            }
        }
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

#pragma mark Scrolling views handlers

- (void) addObservedView:(UIView *)view {
    if (![self.observedViews containsObject:view]) {
        [self.observedViews addObject:view];
        [self addObserverToView:view];
    }
}

- (void) removeObservedViews {
    for (UIView *view in self.observedViews) {
        [self removeObserverFromView:view];
    }
    [self.observedViews removeAllObjects];
}

- (void) scrollView:(UIScrollView*)scrollView setContentOffset:(CGPoint)offset {
    _isObserving = NO;
    scrollView.contentOffset = offset;
    _isObserving = YES;
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end

@interface MXSegmentedPager ()
@property (nonatomic, strong) MXScrollView * scrollView;
@property (nonatomic, assign) BOOL changeContainerFrame;
@end

@implementation MXSegmentedPager (ParallaxHeader)

static void * const kMXSegmentedPagerKVOContext = (void*)&kMXSegmentedPagerKVOContext;
static NSString* const kFrameKeyPath = @"frame";
static NSString* const kSegmentedControlPositionKeyPath = @"segmentedControlPosition";

#pragma mark VGParallaxHeader

- (void)setParallaxHeaderView:(UIView *)view mode:(VGParallaxHeaderMode)mode height:(CGFloat)height {
    [self.scrollView setParallaxHeaderView:view mode:mode height:height];
}

- (VGParallaxHeader *)parallaxHeader {
    return self.scrollView.parallaxHeader;
}

#pragma mark Properties

- (MXScrollView *)scrollView {
    MXScrollView *_scrollView = objc_getAssociatedObject(self, @selector(scrollView));
    if (!_scrollView) {

        // Create scroll-view
        _scrollView = [[MXScrollView alloc] init];
        _scrollView.segmentedPager = self;

        //Organize subviews
        [self addSubview:_scrollView];
        [_scrollView addSubview:self.pager];
        if(self.segmentedControlPosition == MXSegmentedControlPositionTop) {
            [_scrollView addSubview:self.segmentedControl];
        }

        //Add constraints to the scroll-view
        _scrollView.translatesAutoresizingMaskIntoConstraints = NO;
        NSDictionary *binding  = @{@"v" : _scrollView};
        [self addConstraints:[NSLayoutConstraint
                              constraintsWithVisualFormat:@"H:|-0-[v]-0-|"
                              options:NSLayoutFormatDirectionLeadingToTrailing
                              metrics:nil
                              views:binding]];

        [self addConstraints:[NSLayoutConstraint
                              constraintsWithVisualFormat:@"V:|-0-[v]-0-|"
                              options:NSLayoutFormatDirectionLeadingToTrailing
                              metrics:nil
                              views:binding]];

        // Add KVO
        [self.pager addObserver:self forKeyPath:kFrameKeyPath options:NSKeyValueObservingOptionNew context:kMXSegmentedPagerKVOContext];
        [self addObserver:self forKeyPath:kSegmentedControlPositionKeyPath options:NSKeyValueObservingOptionNew context:kMXSegmentedPagerKVOContext];

        self.changeContainerFrame = YES;

        objc_setAssociatedObject(self, @selector(scrollView), _scrollView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return _scrollView;
}

- (void)setScrollView:(MXScrollView *)scrollView {
    objc_setAssociatedObject(self, @selector(scrollView), scrollView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (CGFloat)minimumHeaderHeight {
    return self.scrollView.minimumHeigth;
}

- (void)setMinimumHeaderHeight:(CGFloat)minimumHeaderHeight {
    self.scrollView.minimumHeigth = minimumHeaderHeight;
}

- (MXProgressBlock)progressBlock {
    return self.scrollView.progressBlock;
}

- (void)setProgressBlock:(MXProgressBlock)progressBlock {
    self.scrollView.progressBlock = progressBlock;
}

- (BOOL)changeContainerFrame {
    NSNumber *number = objc_getAssociatedObject(self, @selector(changeContainerFrame));
    return [number boolValue];
}

- (void)setChangeContainerFrame:(BOOL)changeContainerFrame {
    NSNumber *number = [NSNumber numberWithBool:changeContainerFrame];
    objc_setAssociatedObject(self, @selector(changeContainerFrame), number , OBJC_ASSOCIATION_RETAIN);
}

#pragma mark KVO

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if (context == kMXSegmentedPagerKVOContext) {
        if ([keyPath isEqualToString:kFrameKeyPath]) {

            if (self.changeContainerFrame) {
                self.changeContainerFrame = NO;

                CGFloat height = self.scrollView.frame.size.height;
                height -= self.segmentedControl.frame.size.height;
                height -= self.scrollView.minimumHeigth;
                height -= self.segmentedControlEdgeInsets.top;
                height -=self.segmentedControlEdgeInsets.bottom;

                self.pager.frame = (CGRect){
                    .origin         = self.pager.frame.origin,
                    .size.width     = self.pager.frame.size.width,
                    .size.height    = height
                };

                self.scrollView.contentSize = CGSizeMake(self.frame.size.width, self.frame.size.height + self.parallaxHeader.frame.size.height - self.minimumHeaderHeight);
                self.changeContainerFrame = YES;
            }
        }
        else if ([keyPath isEqualToString:kSegmentedControlPositionKeyPath]) {
            if(self.segmentedControlPosition == MXSegmentedControlPositionBottom) {
                [self addSubview:self.segmentedControl];
            }
            else {
                [self.scrollView addSubview:self.segmentedControl];
            }
        }
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<TITLE>
TabAdapter
</TITLE>

<META NAME="date" CONTENT="2014-04-29">

<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../stylesheet.css" TITLE="Style">

      Overview
      Package
    Class
      Use
      Tree
      Deprecated
      Index
      Help

 PREV CLASS
 NEXT CLASS

  FRAMES
 NO FRAMES

  All Classes

  SUMMARY: NESTED | FIELD | CONSTR | METHOD

DETAIL: FIELD | CONSTR | METHOD

com.example.tson

Class TabAdapter

java.lang.Object
  android.support.v4.view.PagerAdapter
      android.support.v4.app.FragmentStatePagerAdapter
          com.example.tson.TabAdapter

public class TabAdapter
extends android.support.v4.app.FragmentStatePagerAdapter

Field Summary

Fields inherited from class android.support.v4.view.PagerAdapter

POSITION_NONE, POSITION_UNCHANGED

Constructor Summary

TabAdapter(android.support.v4.app.FragmentManager fm)

Method Summary

 int
getCount()

 android.support.v4.app.Fragment
getItem(int i)

Methods inherited from class android.support.v4.app.FragmentStatePagerAdapter

destroyItem, finishUpdate, instantiateItem, isViewFromObject, restoreState, saveState, setPrimaryItem, startUpdate

Methods inherited from class android.support.v4.view.PagerAdapter

destroyItem, finishUpdate, getItemPosition, getPageTitle, getPageWidth, instantiateItem, notifyDataSetChanged, registerDataSetObserver, setPrimaryItem, startUpdate, unregisterDataSetObserver

Methods inherited from class java.lang.Object

equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructor Detail

TabAdapter

public TabAdapter(android.support.v4.app.FragmentManager fm)

Method Detail

getItem

public android.support.v4.app.Fragment getItem(int i)

Specified by:
getItem in class android.support.v4.app.FragmentStatePagerAdapter

getCount

public int getCount()

Specified by:
getCount in class android.support.v4.view.PagerAdapter

      Overview
      Package
    Class
      Use
      Tree
      Deprecated
      Index
      Help

 PREV CLASS
 NEXT CLASS

  FRAMES
 NO FRAMES

  All Classes

  SUMMARY: NESTED | FIELD | CONSTR | METHOD

DETAIL: FIELD | CONSTR | METHOD


text:
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package co.edu.uniandes.csw.artwork.tests.dto;

import co.edu.uniandes.csw.artwork.dtos.minimum.MessageDTO;
import co.edu.uniandes.csw.artwork.entities.MessageEntity;
import java.io.File;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.UserTransaction;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.resolver.api.maven.Maven;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import uk.co.jemos.podam.api.PodamFactory;
import uk.co.jemos.podam.api.PodamFactoryImpl;

@RunWith(Arquillian.class)
public class MessageDTOTest {
    PodamFactory factory = new PodamFactoryImpl();

    private static MessageEntity messageEntity;

    @PersistenceContext(unitName = "ArtworkPU")
    private EntityManager em;

    @Inject
    private UserTransaction utx;

    @Deployment
    public static WebArchive createDeployment() {
        return ShrinkWrap.create(WebArchive.class)
                // Se agrega las dependencias
                .addAsLibraries(Maven.resolver().loadPomFromFile("pom.xml")
                        .importRuntimeDependencies().resolve()
                        .withTransitivity().asFile())
                // Se agregan los compilados de los paquetes de servicios
                .addPackage(MessageDTO.class.getPackage())
                // El archivo que contiene la configuracion a la base de datos.
                .addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml")
                // El archivo beans.xml es necesario para injeccion de dependencias.
                .addAsWebInfResource(new File("src/main/webapp/WEB-INF/beans.xml"))
                // El archivo shiro.ini es necesario para injeccion de dependencias
                .addAsWebInfResource(new File("src/main/webapp/WEB-INF/shiro.ini"))
                // El archivo web.xml es necesario para el despliegue de los servlets
                .setWebXML(new File("src/main/webapp/WEB-INF/web.xml"));
    }

    private void clearData() {
        em.createQuery("delete from MessageEntity").executeUpdate();
        messageEntity = null;
    }

    public void insertData() {
        messageEntity = factory.manufacturePojo(MessageEntity.class);
        messageEntity.setId(1L);
        em.persist(messageEntity);
    }

    @Before
    public void setUpTest() {
        try {
            utx.begin();
            clearData();
            insertData();
            utx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                utx.rollback();
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
    }

    @Test
    public void setgetId() {
        MessageDTO item = factory.manufacturePojo(MessageDTO.class);

        MessageDTO newItem = new MessageDTO();
        newItem.setId(item.getId());

        Assert.assertEquals(item.getId(), newItem.getId());
    }

    @Test
    public void setgetBody() {
        MessageDTO message = factory.manufacturePojo(MessageDTO.class);

        MessageDTO newMessage = new MessageDTO();
        newMessage.setBody(message.getBody());

        Assert.assertEquals(message.getBody(), newMessage.getBody());
    }

    @Test
    public void setgetSubject() {
        MessageDTO message = factory.manufacturePojo(MessageDTO.class);

        MessageDTO newMessage = new MessageDTO();
        newMessage.setSubject(message.getSubject());

        Assert.assertEquals(message.getSubject(), newMessage.getSubject());
    }

    @Test
    public void setgetSentDate() {
        MessageDTO message = factory.manufacturePojo(MessageDTO.class);

        MessageDTO newMessage = new MessageDTO();
        newMessage.setSentDate(message.getSentDate());

        Assert.assertEquals(message.getSentDate(), newMessage.getSentDate());
    }

    @Test
    public void setgetClient() {
        MessageDTO message = factory.manufacturePojo(MessageDTO.class);

        MessageDTO newMessage = new MessageDTO();
        newMessage.setClient(message.getClient());

        Assert.assertEquals(message.getClient(), newMessage.getClient());
    }

    @Test
    public void entity2DTO() {
        MessageDTO artist = new MessageDTO(messageEntity);

        Assert.assertEquals(artist.getBody(), messageEntity.getBody());
        Assert.assertEquals(artist.getId(), messageEntity.getId());
        Assert.assertEquals(artist.getSubject(), messageEntity.getSubject());
        Assert.assertEquals(artist.getSentDate(), messageEntity.getSentDate());
    }
}