text:
package org.dosomething.android.transfer;

import android.content.Intent;

import org.dosomething.android.DSConstants;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

public class Campaign implements Serializable {

	private static final long serialVersionUID = 1L;
	private static final SimpleDateFormat df = new SimpleDateFormat("MM/dd/yy", Locale.US);

	private String id;
	private String name;
	private String logoUrl;
	private Date startDate;
	private Date endDate;
	private String teaser;
	private String backgroundColor;
	private String backgroundUrl;
	private String callout;
	private int minVersion;
	private int[] cause_tags;
	private int gid;
	private int order;
	private boolean hidden;
	private DSConstants.CAMPAIGN_TYPE campaignType;

	private String videoUrl;
	private String videoThumbnail;
	private String additionalText;
	private String link;
	private String image;
	private String shareTitle;
	private String shareMessage;
	private String signUpAltLink;
	private String signUpAltText;
	private String signUpSmsAction;
	private int signUpSmsOptIn;

	private String smsReferText;
	private int mCommonsAlphaOptIn;
	private int mCommonsBetaOptIn;

	private List<Faq> faqs;
	private Gallery gallery;
	private List<HowTo> howTos;
	private People people;
	private Prize prize;
	private MoreInfo moreInfo;
	private List<Resource> resources;
	private List<Challenge> challenges;
	private WebForm reportBack;
	private WebForm signUp;
	private SFGData sfgData;

    // List of data to display in the Do It campaign section
    private List<ICampaignSectionData> mDoItData;

    // List of data to display in the Learn campaign section
    private List<ICampaignSectionData> mLearnData;

    // List of data to display in the Plan campaign section
    private List<ICampaignSectionData> mPlanData;

	public Campaign() {}

	public Campaign(String id, JSONObject obj) throws JSONException, ParseException {

		JSONObject co = obj.getJSONObject("campaign");

		this.id = id;

		name = co.getString("campaign-name");
		backgroundColor = "#" + co.getString("logo-bg-color");
		startDate = df.parse(co.getString("start-date"));
		endDate = df.parse(co.getString("end-date"));
		logoUrl = co.getString("logo");
		backgroundUrl = co.optString("logo-bg-image",null);
		callout = co.optString("call-to-action",null);
		gid = co.optInt("gid", -1);
		order = co.getInt("order");
		hidden = co.optBoolean("hidden", false);
		smsReferText = co.optString("sms-refer-text");
		mCommonsAlphaOptIn = co.optInt("mcommons-optin", -1);
		mCommonsBetaOptIn = co.optInt("mcommons-friend-optin", -1);
		minVersion = co.optInt("android-min-version", 0);

		JSONArray ct = co.optJSONArray("causes-tags");
		if(ct!=null) {
			int numTags = ct.length();
			if(numTags > 0)
				cause_tags = new int[11];	// 11 for number of causes

			for(int i=0; i<numTags; i++) {
				int tag = ct.getInt(i);
				cause_tags[i] = tag;
			}
		}

		// Convert campaign-type to its enum value
		String strCampaignType = co.optString("campaign-type",null);
		if (strCampaignType != null) {
			if (strCampaignType.equals("change-a-mind"))
				campaignType = DSConstants.CAMPAIGN_TYPE.CHANGE_A_MIND;
			else if (strCampaignType.equals("donation"))
				campaignType = DSConstants.CAMPAIGN_TYPE.DONATION;
			else if (strCampaignType.equals("help-1-person"))
				campaignType = DSConstants.CAMPAIGN_TYPE.HELP_1_PERSON;
			else if (strCampaignType.equals("improve-a-place"))
				campaignType = DSConstants.CAMPAIGN_TYPE.IMPROVE_A_PLACE;
			else if (strCampaignType.equals("made-by-you"))
				campaignType = DSConstants.CAMPAIGN_TYPE.MADE_BY_YOU;
			else if (strCampaignType.equals("share-for-good"))
				campaignType = DSConstants.CAMPAIGN_TYPE.SHARE_FOR_GOOD;
			else if (strCampaignType.equals("sms"))
				campaignType = DSConstants.CAMPAIGN_TYPE.SMS;
		}

		JSONObject m = obj.optJSONObject("main");
		if(m!=null) {
			teaser = m.optString("teaser",null);
			videoUrl = m.optString("video",null);
			videoThumbnail = m.optString("video-thumbnail",null);
			additionalText = m.optString("additional-text",null);
			link = m.optString("link",null);
			image = m.optString("image",null);
			shareTitle = m.optString("share-title",null);
			shareMessage = m.optString("share-message",null);
			signUpAltLink = m.optString("sign-up-alt-link",null);
			signUpAltText = m.optString("sign-up-alt-text",null);
			signUpSmsAction = m.optString("sign-up-sms-action",null);
			signUpSmsOptIn = m.optInt("sign-up-sms-opt-in", 0);
		}

		JSONArray f = obj.optJSONArray("faq");
		if(f!=null) {
			faqs = new ArrayList<Faq>(f.length());
			for(int i=0; i<f.length(); i++) {
				faqs.add(new Faq(f.getJSONObject(i)));
			}
		}

		JSONObject g = obj.optJSONObject("gallery");
		if(g!=null) {
			gallery = new Gallery(g);
		}

		JSONArray h = obj.optJSONArray("how-to");
		if(h!=null) {
			howTos = new ArrayList<HowTo>(h.length());
			for(int i=0; i<h.length(); i++) {
				howTos.add(new HowTo(h.getJSONObject(i)));
			}
		}

		JSONObject jsonPeople = obj.optJSONObject("people");
		if (jsonPeople != null) {
			people = new People(jsonPeople);
		}

		JSONObject p = obj.optJSONObject("prizes");
		if(p!=null) {
			prize = new Prize(p);
		}

		JSONObject mi = obj.optJSONObject("more-info");
		if (mi != null) {
			moreInfo = new MoreInfo(mi);
		}

		JSONArray r = obj.optJSONArray("resources");
		if(r!=null) {
			resources = new ArrayList<Resource>(r.length());
			for(int i=0; i<r.length(); i++) {
				resources.add(new Resource(r.getJSONObject(i)));
			}
		}

		JSONArray c = obj.optJSONArray("challenges");
		if(c!=null) {
			challenges = new ArrayList<Challenge>(c.length());
			for(int i=0; i<c.length(); i++) {
				challenges.add(new Challenge(c.getJSONObject(i)));
			}
		}

		JSONObject rb = obj.optJSONObject("report-back");
		if(rb!=null) {
			reportBack = new WebForm(rb);
		}

		JSONObject su = obj.optJSONObject("sign-up");
		if(su!=null) {
			signUp = new WebForm(su);
		}

		JSONObject sfg = obj.optJSONObject("sfg-data");
		if (sfg != null) {
			sfgData = new SFGData(sfg);
		}

        JSONArray doItData = obj.optJSONArray("do-it");
        if (doItData != null) {
            mDoItData = convertToSectionData(doItData);
        }

        JSONArray learnData = obj.optJSONArray("learn");
        if (learnData != null) {
            mLearnData = convertToSectionData(learnData);
        }

        JSONArray planData = obj.optJSONArray("plan");
        if (planData != null) {
            mPlanData = convertToSectionData(planData);
        }
	}

    /**
     * Convert JSONArray of section data to an ICampaignSectionData list.
     *
     * @param jsonData JSONArray of section data
     * @return Converted list of ICampaignSectionData objects
     * @throws JSONException
     */
    private List<ICampaignSectionData> convertToSectionData(JSONArray jsonData) throws JSONException {
        ArrayList<ICampaignSectionData> sectionData = new ArrayList<ICampaignSectionData>(jsonData.length());

        for (int i = 0; i < jsonData.length(); i++) {
            JSONObject data = jsonData.getJSONObject(i);
            String type = data.getString("type");
            if (type.equals(CampaignTextImageData.TYPE_ID)) {
                sectionData.add(new CampaignTextImageData(data));
            }
            else if (type.equals(CampaignImageTextData.TYPE_ID)) {
                sectionData.add(new CampaignImageTextData(data));
            }
            else if (type.equals(CampaignGalleryData.TYPE_ID)) {
                sectionData.add(new CampaignGalleryData(data));
            }
        }

        return sectionData;
    }

	public JSONObject toJSON() throws JSONException {
		JSONObject obj = new JSONObject();

		JSONObject jsonCampaign = new JSONObject();
		jsonCampaign.put("campaign-name", name);
		// Remove '#' from color value
		String logoBgColor = backgroundColor.substring(1);
		jsonCampaign.put("logo-bg-color", logoBgColor);
		jsonCampaign.put("start-date", new SimpleDateFormat("MM/dd/yy", Locale.US).format(startDate));
		jsonCampaign.put("end-date", new SimpleDateFormat("MM/dd/yy", Locale.US).format(endDate));
		jsonCampaign.put("logo", logoUrl);
		jsonCampaign.put("logo-bg-image", backgroundUrl);
		jsonCampaign.put("call-to-action", callout);
		jsonCampaign.put("gid", gid);
		jsonCampaign.put("hidden", hidden);
		jsonCampaign.put("order", order);
		jsonCampaign.put("sms-refer-text", smsReferText);
		jsonCampaign.put("mcommons-optin", mCommonsAlphaOptIn);
		jsonCampaign.put("mcommons-friend-optin", mCommonsBetaOptIn);
		jsonCampaign.put("android-min-version", minVersion);
		obj.put("campaign", jsonCampaign);

		if (cause_tags != null) {
			JSONArray jsonTags = new JSONArray();
			for (int i = 0; i < cause_tags.length; i++) {
				jsonTags.put(cause_tags[i]);
			}
			obj.put("causes-tags", jsonTags);
		}

		if (campaignType != null) {
			String cType = "";
			if (campaignType == DSConstants.CAMPAIGN_TYPE.CHANGE_A_MIND)
				cType = "change-a-mind";
			else if (campaignType == DSConstants.CAMPAIGN_TYPE.DONATION)
				cType = "donation";
			else if (campaignType == DSConstants.CAMPAIGN_TYPE.HELP_1_PERSON)
				cType = "help-1-person";
			else if (campaignType == DSConstants.CAMPAIGN_TYPE.IMPROVE_A_PLACE)
				cType = "improve-a-place";
			else if (campaignType == DSConstants.CAMPAIGN_TYPE.MADE_BY_YOU)
				cType = "made-by-you";
			else if (campaignType == DSConstants.CAMPAIGN_TYPE.SHARE_FOR_GOOD)
				cType = "share-for-good";
			else if (campaignType == DSConstants.CAMPAIGN_TYPE.SMS)
				cType = "sms";

			obj.put("campaign-type", cType);
		}

		obj.put("campaign", jsonCampaign);

		JSONObject main = new JSONObject();
		main.put("teaser", teaser);
		main.put("video", videoUrl);
		main.put("video-thumbnail", videoThumbnail);
		main.put("additional-text", additionalText);
		main.put("link", link);
		main.put("image", image);
		main.put("share-title", shareTitle);
		main.put("share-message", shareMessage);
		main.put("sign-up-alt-link", signUpAltLink);
		main.put("sign-up-alt-text", signUpAltText);
		main.put("sign-up-sms-action", signUpSmsAction);
		main.put("sign-up-sms-opt-in", signUpSmsOptIn);
		obj.put("main", main);

		if (faqs != null && faqs.size() > 0) {
			JSONArray jsonFaqs = new JSONArray();
			for (Faq f : faqs) {
				jsonFaqs.put(f.toJSON());
			}
			obj.put("faq", jsonFaqs);
		}

		if (gallery != null)
			obj.put("gallery", gallery.toJSON());

		if (howTos != null && howTos.size() > 0) {
			JSONArray jsonHowTos = new JSONArray();
			for (HowTo h : howTos) {
				jsonHowTos.put(h.toJSON());
			}
			obj.put("how-to", jsonHowTos);
		}

		if (people != null)
			obj.put("people", people.toJSON());

		if (prize != null)
			obj.put("prizes", prize.toJSON());

		if (moreInfo != null)
			obj.put("more-info", moreInfo.toJSON());

		if (resources != null && resources.size() > 0) {
			JSONArray jsonResources = new JSONArray();
			for (Resource r : resources) {
				jsonResources.put(r.toJSON());
			}
			obj.put("resources", jsonResources);
		}

		if (challenges != null && challenges.size() > 0) {
			JSONArray jsonChallenges = new JSONArray();
			for (Challenge c : challenges) {
				jsonChallenges.put(c.toJSON());
			}
			obj.put("challenges", jsonChallenges);
		}

		if (reportBack != null)
			obj.put("report-back", reportBack.toJSON());

		if (signUp != null)
			obj.put("sign-up", signUp.toJSON());

		if (sfgData != null)
			obj.put("sfg-data", sfgData.toJSON());

        if (mDoItData != null && mDoItData.size() > 0) {
            JSONArray doItData = new JSONArray();
            for (ICampaignSectionData data : mDoItData) {
                doItData.put(data.toJSON());
            }
            obj.put("do-it", doItData);
        }

        if (mLearnData != null && mLearnData.size() > 0) {
            JSONArray learnData = new JSONArray();
            for (ICampaignSectionData data : mLearnData) {
                learnData.put(data.toJSON());
            }
            obj.put("learn", learnData);
        }

        if (mPlanData != null && mPlanData.size() > 0) {
            JSONArray planData = new JSONArray();
            for (ICampaignSectionData data : mPlanData) {
                planData.put(data.toJSON());
            }
            obj.put("plan", planData);
        }

		JSONObject namedObj = new JSONObject();
		namedObj.put(id, obj);

		return namedObj;
	}

	public Intent getShareIntent(){
		Intent answer = new Intent(android.content.Intent.ACTION_SEND);

		if(!nullOrEmpty(shareTitle)){
			answer.putExtra(android.content.Intent.EXTRA_SUBJECT, shareTitle);
		}

		answer.putExtra(android.content.Intent.EXTRA_TEXT, shareMessage);
		answer.setType("text/plain");
		return answer;
	}

	private static boolean nullOrEmpty(String str){
		return str == null || str.trim().length() == 0;
	}

	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getLogoUrl() {
		return logoUrl;
	}
	public void setLogoUrl(String logoUrl) {
		this.logoUrl = logoUrl;
	}
	public Date getStartDate() {
		return startDate;
	}
	public void setStartDate(Date startDate) {
		this.startDate = startDate;
	}
	public Date getEndDate() {
		return endDate;
	}
	public void setEndDate(Date endDate) {
		this.endDate = endDate;
	}
	public String getBackgroundColor() {
		return backgroundColor;
	}
	public void setBackgroundColor(String backgroundColor) {
		this.backgroundColor = backgroundColor;
	}
	public String getTeaser() {
		return teaser;
	}
	public void setTeaser(String teaser) {
		this.teaser = teaser;
	}
	public String getVideoUrl() {
		return videoUrl;
	}
	public void setVideoUrl(String videoUrl) {
		this.videoUrl = videoUrl;
	}
	public String getAdditionalText() {
		return additionalText;
	}
	public void setAdditionalText(String additionalText) {
		this.additionalText = additionalText;
	}

	public String getVideoThumbnail() {
		return videoThumbnail;
	}

	public void setVideoThumbnail(String videoThumbnail) {
		this.videoThumbnail = videoThumbnail;
	}

	public String getLink() {
		return link;
	}

	public void setLink(String link) {
		this.link = link;
	}

	public String getImage() {
		return image;
	}

	public void setImage(String image) {
		this.image = image;
	}

	public List<Faq> getFaqs() {
		return faqs;
	}

	public void setFaqs(List<Faq> faqs) {
		this.faqs = faqs;
	}

	public Gallery getGallery() {
		return gallery;
	}

	public void setGallery(Gallery gallery) {
		this.gallery = gallery;
	}

	public List<HowTo> getHowTos() {
		return howTos;
	}

	public void setHowTos(List<HowTo> howTos) {
		this.howTos = howTos;
	}

	public People getPeople() {
		return people;
	}

	public Prize getPrize() {
		return prize;
	}

	public void setPrize(Prize prize) {
		this.prize = prize;
	}

	public MoreInfo getMoreInfo() {
		return moreInfo;
	}

	public List<Resource> getResources() {
		return resources;
	}

	public void setResources(List<Resource> resources) {
		this.resources = resources;
	}

	public List<Challenge> getChallenges() {
		return challenges;
	}

	public void setChallenges(List<Challenge> challenges) {
		this.challenges = challenges;
	}

	public WebForm getReportBack() {
		return reportBack;
	}

	public void setReportBack(WebForm reportBack) {
		this.reportBack = reportBack;
	}

	public WebForm getSignUp() {
		return signUp;
	}

	public void setSignUp(WebForm signUp) {
		this.signUp = signUp;
	}

	public SFGData getSFGData() {
		return sfgData;
	}

	public String getShareTitle() {
		return shareTitle;
	}

	public void setShareTitle(String shareTitle) {
		this.shareTitle = shareTitle;
	}

	public String getShareMessage() {
		return shareMessage;
	}

	public String getSignUpAltLink() {
		return signUpAltLink;
	}

	public String getSignUpAltText() {
		return signUpAltText;
	}

	public String getSignUpSmsAction() {
		return signUpSmsAction;
	}

	public int getSignUpSmsOptIn() {
		return signUpSmsOptIn;
	}

	public void setShareMessage(String shareMessage) {
		this.shareMessage = shareMessage;
	}
	public String getBackgroundUrl() {
		return backgroundUrl;
	}

	public void setBackgroundUrl(String backgroundUrl) {
		this.backgroundUrl = backgroundUrl;
	}

	public String getCallout() {
		return callout;
	}

	public DSConstants.CAMPAIGN_TYPE getCampaignType() {
		return campaignType;
	}

	public int getMinVersion() {
		return minVersion;
	}

	public int[] getCauseTags() {
		return cause_tags;
	}

	public int getGid() {
		return gid;
	}

	public boolean isHidden() {
		return hidden;
	}

	public int getOrder() {
		return order;
	}

	public String getSMSReferText() {
		return smsReferText;
	}

	public int getMCommonsAlphaOptIn() {
		return mCommonsAlphaOptIn;
	}

	public int getMCommonsBetaOptIn() {
		return mCommonsBetaOptIn;
	}

    public List<ICampaignSectionData> getDoItData() {
        return mDoItData;
    }

    public List<ICampaignSectionData> getLearnData() {
        return mLearnData;
    }

    public List<ICampaignSectionData> getPlanData() {
        return mPlanData;
    }
}


text:
// Template Source: BaseEntityRequestBuilder.java.tt
// ------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All Rights Reserved.  Licensed under the MIT License.  See License in the project root for license information.
// ------------------------------------------------------------------------------

package com.microsoft.graph.requests;

import com.microsoft.graph.http.IRequestBuilder;
import com.microsoft.graph.core.ClientException;
import com.microsoft.graph.models.BaseItem;
import java.util.Arrays;
import java.util.EnumSet;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
import com.microsoft.graph.core.IBaseClient;
import com.microsoft.graph.http.BaseRequestBuilder;

// **NOTE** This file was generated by a tool and any changes will be overwritten.

/**
 * The class for the Base Item Request Builder.
 */
public class BaseItemRequestBuilder extends BaseRequestBuilder<BaseItem> {

    /**
     * The request builder for the BaseItem
     *
     * @param requestUrl     the request URL
     * @param client         the service client
     * @param requestOptions the options for this request
     */
    public BaseItemRequestBuilder(@Nonnull final String requestUrl, @Nonnull final IBaseClient<?> client, @Nullable final java.util.List<? extends com.microsoft.graph.options.Option> requestOptions) {
        super(requestUrl, client, requestOptions);
    }

    /**
     * Creates the request
     *
     * @param requestOptions the options for this request
     * @return the BaseItemRequest instance
     */
    @Nonnull
    public BaseItemRequest buildRequest(@Nullable final com.microsoft.graph.options.Option... requestOptions) {
        return buildRequest(getOptions(requestOptions));
    }

    /**
     * Creates the request with specific requestOptions instead of the existing requestOptions
     *
     * @param requestOptions the options for this request
     * @return the BaseItemRequest instance
     */
    @Nonnull
    public BaseItemRequest buildRequest(@Nonnull final java.util.List<? extends com.microsoft.graph.options.Option> requestOptions) {
        return new com.microsoft.graph.requests.BaseItemRequest(getRequestUrl(), getClient(), requestOptions);
    }

    /**
     * Gets the request builder for User
     *
     * @return the UserWithReferenceRequestBuilder instance
     */
    @Nonnull
    public com.microsoft.graph.requests.UserWithReferenceRequestBuilder createdByUser() {
        return new com.microsoft.graph.requests.UserWithReferenceRequestBuilder(getRequestUrlWithAdditionalSegment("createdByUser"), getClient(), null);
    }

    /**
     * Gets the request builder for User
     *
     * @return the UserWithReferenceRequestBuilder instance
     */
    @Nonnull
    public com.microsoft.graph.requests.UserWithReferenceRequestBuilder lastModifiedByUser() {
        return new com.microsoft.graph.requests.UserWithReferenceRequestBuilder(getRequestUrlWithAdditionalSegment("lastModifiedByUser"), getClient(), null);
    }
}

redpajama_set_name: RedPajamaGithub


text:
package org.jbpm.casemgmt.impl;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static org.jbpm.kie.services.impl.CommonUtils.getAuthenticatedUserRoles;
import static org.kie.internal.query.QueryParameterIdentifiers.FILTER;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.jbpm.casemgmt.api.CaseNotFoundException;
import org.jbpm.casemgmt.api.CaseRuntimeDataService;
import org.jbpm.casemgmt.api.auth.AuthorizationManager;
import org.jbpm.casemgmt.api.generator.CaseIdGenerator;
import org.jbpm.casemgmt.api.model.AdHocFragment;
import org.jbpm.casemgmt.api.model.CaseDefinition;
import org.jbpm.casemgmt.api.model.CaseFileItem;
import org.jbpm.casemgmt.api.model.CaseMilestone;
import org.jbpm.casemgmt.api.model.CaseRole;
import org.jbpm.casemgmt.api.model.CaseStage;
import org.jbpm.casemgmt.api.model.CaseStatus;
import org.jbpm.casemgmt.api.model.instance.CaseInstance;
import org.jbpm.casemgmt.api.model.instance.CaseMilestoneInstance;
import org.jbpm.casemgmt.api.model.instance.CaseStageInstance;
import org.jbpm.casemgmt.api.model.instance.StageStatus;
import org.jbpm.casemgmt.impl.model.AdHocFragmentImpl;
import org.jbpm.casemgmt.impl.model.CaseDefinitionComparator;
import org.jbpm.casemgmt.impl.model.CaseDefinitionImpl;
import org.jbpm.casemgmt.impl.model.CaseMilestoneImpl;
import org.jbpm.casemgmt.impl.model.CaseRoleImpl;
import org.jbpm.casemgmt.impl.model.CaseStageImpl;
import org.jbpm.casemgmt.impl.model.ProcessDefinitionComparator;
import org.jbpm.casemgmt.impl.model.instance.CaseMilestoneInstanceImpl;
import org.jbpm.casemgmt.impl.model.instance.CaseStageInstanceImpl;
import org.jbpm.kie.services.impl.model.NodeInstanceDesc;
import org.jbpm.kie.services.impl.model.ProcessAssetDesc;
import org.jbpm.kie.services.impl.security.DeploymentRolesManager;
import org.jbpm.runtime.manager.impl.AbstractRuntimeManager;
import org.jbpm.services.api.DeploymentEvent;
import org.jbpm.services.api.DeploymentEventListener;
import org.jbpm.services.api.RuntimeDataService;
import org.jbpm.services.api.model.DeployedAsset;
import org.jbpm.services.api.model.ProcessDefinition;
import org.jbpm.services.api.model.ProcessInstanceDesc;
import org.jbpm.services.api.service.ServiceRegistry;
import org.jbpm.shared.services.impl.QueryManager;
import org.jbpm.shared.services.impl.TransactionalCommandService;
import org.jbpm.shared.services.impl.commands.QueryNameCommand;
import org.jbpm.workflow.core.WorkflowProcess;
import org.jbpm.workflow.core.node.BoundaryEventNode;
import org.jbpm.workflow.core.node.DynamicNode;
import org.jbpm.workflow.core.node.MilestoneNode;
import org.jbpm.workflow.core.node.StartNode;
import org.kie.api.KieBase;
import org.kie.api.definition.process.Node;
import org.kie.api.definition.process.NodeContainer;
import org.kie.api.definition.process.Process;
import org.kie.api.runtime.process.ProcessInstance;
import org.kie.api.runtime.query.QueryContext;
import org.kie.api.task.model.Status;
import org.kie.api.task.model.TaskSummary;
import org.kie.internal.KieInternalServices;
import org.kie.internal.identity.IdentityProvider;
import org.kie.internal.process.CorrelationKey;
import org.kie.internal.process.CorrelationKeyFactory;

public class CaseRuntimeDataServiceImpl implements CaseRuntimeDataService, DeploymentEventListener {

    protected Set<CaseDefinitionImpl> availableCases = new HashSet<CaseDefinitionImpl>();
    protected Set<ProcessDefinition> availableProcesses = new HashSet<ProcessDefinition>();

    private CorrelationKeyFactory correlationKeyFactory = KieInternalServices.Factory.get().newCorrelationKeyFactory();

    private CaseIdGenerator caseIdGenerator;

    private RuntimeDataService runtimeDataService;
    private TransactionalCommandService commandService;

    private IdentityProvider identityProvider;
    private DeploymentRolesManager deploymentRolesManager = new DeploymentRolesManager();

    // default statuses set to active only
    private List<CaseStatus> statuses = Arrays.asList(CaseStatus.OPEN);

    private static final List<Status> allActiveStatus = Arrays.asList(
        Status.Created,
        Status.Ready,
        Status.Reserved,
        Status.InProgress,
        Status.Suspended
      );

    public CaseRuntimeDataServiceImpl() {
        QueryManager.get().addNamedQueries("META-INF/CaseMgmtorm.xml");

        ServiceRegistry.get().register(CaseRuntimeDataService.class.getSimpleName(), this);
    }

    public CaseIdGenerator getCaseIdGenerator() {
        return caseIdGenerator;
    }

    public void setCaseIdGenerator(CaseIdGenerator caseIdGenerator) {
        this.caseIdGenerator = caseIdGenerator;
    }

    public void setRuntimeDataService(RuntimeDataService runtimeDataService) {
        this.runtimeDataService = runtimeDataService;
    }

    public void setCommandService(TransactionalCommandService commandService) {
        this.commandService = commandService;
    }

    public void setIdentityProvider(IdentityProvider identityProvider) {
        this.identityProvider = identityProvider;
    }

    public void setDeploymentRolesManager(DeploymentRolesManager deploymentRolesManager) {
        this.deploymentRolesManager = deploymentRolesManager;
    }

    /*
     * Deploy and undeploy handling
     */
    @Override
    public void onDeploy(DeploymentEvent event) {
        AbstractRuntimeManager runtimeManager = (AbstractRuntimeManager) event.getDeployedUnit().getRuntimeManager();
        KieBase kieBase = runtimeManager.getEnvironment().getKieBase();
        Collection<Process> processes = kieBase.getProcesses();

        Map<String, DeployedAsset> mapProcessById = event.getDeployedUnit().getDeployedAssets()
                                                                            .stream()
                                                                            .collect(toMap(DeployedAsset::getId, asset -> asset));
        for( Process process : processes ) {
            if( ((WorkflowProcess)process).isDynamic()) {
                String caseIdPrefix = collectCaseIdPrefix(process);
                Collection<CaseMilestone> caseMilestones = collectMilestoness(process);
                Collection<CaseStage> caseStages = collectCaseStages(event.getDeploymentId(), process.getId(), ((WorkflowProcess)process));
                Collection<CaseRole> caseRoles = collectCaseRoles(process);
                Collection<AdHocFragment> adHocFragments = collectAdHocFragments((WorkflowProcess)process);

                CaseDefinitionImpl caseDef = new CaseDefinitionImpl((ProcessAssetDesc) mapProcessById.get(process.getId()), caseIdPrefix, caseStages, caseMilestones, caseRoles, adHocFragments);

                availableCases.add(caseDef);
                caseIdGenerator.register(caseIdPrefix);
            }
        }

        // collect role information
        Collection<DeployedAsset> assets = event.getDeployedUnit().getDeployedAssets();
        List<String> roles = null;
        for( DeployedAsset asset : assets ) {
            if( asset instanceof ProcessAssetDesc ) {
                // if it's not dynamic it's considered as not case definition
                if (!((ProcessAssetDesc) asset).isDynamic()) {
                    availableProcesses.add((ProcessAssetDesc) asset);
                }
                if (roles == null) {
                    roles = ((ProcessAssetDesc) asset).getRoles();
                }
            }
        }
        if (roles == null) {
            roles = Collections.emptyList();
        }
        deploymentRolesManager.addRolesForDeployment(event.getDeploymentId(), roles);

    }

    @Override
    public void onUnDeploy(DeploymentEvent event) {

        Collection<CaseDefinitionImpl> undeployed = availableCases.stream()
                    .filter(caseDef -> caseDef.getDeploymentId().equals(event.getDeploymentId()))
                    .collect(toList());

        availableCases.removeAll(undeployed);

        Collection<ProcessDefinition> undeployedProcesses = availableProcesses.stream()
                .filter(process -> process.getDeploymentId().equals(event.getDeploymentId()))
                .collect(toList());

        availableProcesses.removeAll(undeployedProcesses);

        undeployed.forEach(caseDef -> caseIdGenerator.unregister(caseDef.getIdentifierPrefix()));
        deploymentRolesManager.removeRolesForDeployment(event.getDeploymentId());

    }

    @Override
    public void onActivate(DeploymentEvent event) {
        // no op - all is done on RuntimeDataService level as CaseDefinition depends on ProcessDefinition
    }

    @Override
    public void onDeactivate(DeploymentEvent event) {
        // no op - all is done on RuntimeDataService level as CaseDefinition depends on ProcessDefinition
    }

    /*
     * CaseDefinition operations
     */

    @Override
    public CaseDefinition getCase(String deploymentId, String caseDefinitionId) {
        return availableCases.stream()
                            .filter(caseDef -> caseDef.getDeploymentId().equals(deploymentId)
                                    && caseDef.getId().equals(caseDefinitionId))
                            .findFirst()
                            .orElse(null);
    }

    @Override
    public Collection<CaseDefinition> getCases(QueryContext queryContext) {
        Collection<CaseDefinition> cases = availableCases.stream()
                .filter(caseDef -> caseDef.isActive())
                .sorted(new CaseDefinitionComparator(queryContext.getOrderBy(), queryContext.isAscending()))
                .skip(queryContext.getOffset())
                .limit(queryContext.getCount())
                .collect(toList());
        return cases;
    }

    @Override
    public Collection<CaseDefinition> getCases(String filter, QueryContext queryContext) {
        String pattern = "(?i)^.*"+filter+".*$";

        Collection<CaseDefinition> cases = availableCases.stream()
                .filter(caseDef -> caseDef.isActive()
                        && (caseDef.getId().matches(pattern) || caseDef.getName().matches(pattern)))
                .sorted(new CaseDefinitionComparator(queryContext.getOrderBy(), queryContext.isAscending()))
                .skip(queryContext.getOffset())
                .limit(queryContext.getCount())
                .collect(toList());
        return cases;
    }

    @Override
    public Collection<CaseDefinition> getCasesByDeployment(String deploymentId, QueryContext queryContext) {
        Collection<CaseDefinition> cases = availableCases.stream()
                .filter(caseDef -> caseDef.isActive() && caseDef.getDeploymentId().equals(deploymentId))
                .sorted(new CaseDefinitionComparator(queryContext.getOrderBy(), queryContext.isAscending()))
                .skip(queryContext.getOffset())
                .limit(queryContext.getCount())
                .collect(toList());
        return cases;
    }

    /*
     * Process definitions related
     */
    @Override
    public Collection<ProcessDefinition> getProcessDefinitions(QueryContext queryContext) {
        Collection<ProcessDefinition> cases = availableProcesses.stream()
                .filter(caseDef -> caseDef.isActive())
                .sorted(new ProcessDefinitionComparator(queryContext.getOrderBy(), queryContext.isAscending()))
                .skip(queryContext.getOffset())
                .limit(queryContext.getCount())
                .collect(toList());
        return cases;
    }

    @Override
    public Collection<ProcessDefinition> getProcessDefinitions(String filter, QueryContext queryContext) {
        String pattern = "(?i)^.*"+filter+".*$";

        Collection<ProcessDefinition> cases = availableProcesses.stream()
                .filter(caseDef -> caseDef.isActive()
                        && (caseDef.getId().matches(pattern) || caseDef.getName().matches(pattern)))
                .sorted(new ProcessDefinitionComparator(queryContext.getOrderBy(), queryContext.isAscending()))
                .skip(queryContext.getOffset())
                .limit(queryContext.getCount())
                .collect(toList());
        return cases;
    }

    @Override
    public Collection<ProcessDefinition> getProcessDefinitionsByDeployment(String deploymentId, QueryContext queryContext) {
        Collection<ProcessDefinition> cases = availableProcesses.stream()
                .filter(caseDef -> caseDef.isActive() && caseDef.getDeploymentId().equals(deploymentId))
                .sorted(new ProcessDefinitionComparator(queryContext.getOrderBy(), queryContext.isAscending()))
                .skip(queryContext.getOffset())
                .limit(queryContext.getCount())
                .collect(toList());
        return cases;
    }

    /*
     * Case instance and its process instances operations
     */

    @Override
    public Collection<ProcessInstanceDesc> getProcessInstancesForCase(String caseId, QueryContext queryContext) {
        CorrelationKey correlationKey = correlationKeyFactory.newCorrelationKey(caseId);

        return runtimeDataService.getProcessInstancesByCorrelationKey(correlationKey, queryContext);
    }

    @Override
    public Collection<ProcessInstanceDesc> getProcessInstancesForCase(String caseId, List<Integer> processStates, QueryContext queryContext) {
        CorrelationKey correlationKey = correlationKeyFactory.newCorrelationKey(caseId);

        return runtimeDataService.getProcessInstancesByCorrelationKeyAndStatus(correlationKey, processStates, queryContext);
    }

    @Override
    public Collection<CaseMilestoneInstance> getCaseInstanceMilestones(String caseId, boolean achievedOnly, QueryContext queryContext) {
        ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceByCorrelationKey(correlationKeyFactory.newCorrelationKey(caseId));
        if (pi == null || !pi.getState().equals(ProcessInstance.STATE_ACTIVE)) {
            throw new CaseNotFoundException("No case instance found with id " + caseId + " or it's not active anymore");
        }
        CorrelationKey correlationKey = correlationKeyFactory.newCorrelationKey(caseId);

        Collection<org.jbpm.services.api.model.NodeInstanceDesc> nodes = runtimeDataService.getNodeInstancesByCorrelationKeyNodeType(correlationKey,
                                                                                Arrays.asList(ProcessInstance.STATE_ACTIVE),
                                                                                Arrays.asList("MilestoneNode"),
                                                                                queryContext);

        Collection<Long> completedNodes = nodes.stream().filter(n -> ((NodeInstanceDesc)n).getType() == 1).map(n -> n.getId()).collect(toList());
        Predicate<org.jbpm.services.api.model.NodeInstanceDesc> filterNodes = null;
        if (achievedOnly) {
            filterNodes = n -> ((NodeInstanceDesc)n).getType() == 1;
        } else {
            filterNodes = n -> ((NodeInstanceDesc)n).getType() == 0;
        }
        List<String> foundMilestones = new ArrayList<>();

        List<CaseMilestoneInstance> milestones = nodes.stream()
        .filter(filterNodes)
        .map(n -> {
            foundMilestones.add(n.getName());
            return new CaseMilestoneInstanceImpl(String.valueOf(n.getId()), n.getName(), completedNodes.contains(n.getId()), n.getDataTimeStamp());
        })
        .collect(toList());

        if (!achievedOnly) {
            // add other milestones that are present in the definition
            CaseDefinition caseDef = getCase(pi.getDeploymentId(), pi.getProcessId());
            caseDef.getCaseMilestones().stream()
            .filter(cm -> !foundMilestones.contains(cm.getName()))
            .map(cm -> new CaseMilestoneInstanceImpl(cm.getId(), cm.getName(), false, null))
            .forEach(cmi -> milestones.add(cmi));
        }

        return applyPagination(milestones, queryContext);
    }

    @Override
    public Collection<CaseStageInstance> getCaseInstanceStages(String caseId, boolean activeOnly, QueryContext queryContext) {
        ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceByCorrelationKey(correlationKeyFactory.newCorrelationKey(caseId));
        if (pi == null || !pi.getState().equals(ProcessInstance.STATE_ACTIVE)) {
            throw new CaseNotFoundException("No case instance found with id " + caseId + " or it's not active anymore");
        }

        CaseDefinition caseDef = getCase(pi.getDeploymentId(), pi.getProcessId());
        List<CaseStageInstance> stages = internalGetCaseStages(caseDef, caseId, activeOnly, queryContext);

        return applyPagination(stages, queryContext);
    }

    /*
     * Case instance queries
     */

    @Override
    public Collection<org.jbpm.services.api.model.NodeInstanceDesc> getActiveNodesForCase(String caseId, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("caseId", caseId + "%");
        applyQueryContext(params, queryContext);
        applyDeploymentFilter(params);
        List<org.jbpm.services.api.model.NodeInstanceDesc> nodeInstances =  commandService.execute(new QueryNameCommand<List<org.jbpm.services.api.model.NodeInstanceDesc>>("getActiveNodesForCase", params));
        return nodeInstances;
    }

    @Override
    public Collection<org.jbpm.services.api.model.NodeInstanceDesc> getCompletedNodesForCase(String caseId, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("caseId", caseId + "%");
        applyQueryContext(params, queryContext);
        applyDeploymentFilter(params);
        List<org.jbpm.services.api.model.NodeInstanceDesc> nodeInstances =  commandService.execute(new QueryNameCommand<List<org.jbpm.services.api.model.NodeInstanceDesc>>("getCompletedNodesForCase", params));
        return nodeInstances;
    }

    @Override
    public Collection<CaseInstance> getCaseInstances(QueryContext queryContext) {

        return getCaseInstances(statuses, queryContext);
    }

    @Override
    public Collection<CaseInstance> getCaseInstances(List<CaseStatus> statuses, QueryContext queryContext) {

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("statuses", resolveCaseStatuses(statuses));
        applyQueryContext(params, queryContext);
        applyDeploymentFilter(params);
        List<CaseInstance> processInstances =  commandService.execute(new QueryNameCommand<List<CaseInstance>>("getCaseInstances", params));

        return processInstances;
    }

    @Override
    public Collection<CaseInstance> getCaseInstancesByDeployment(String deploymentId, List<CaseStatus> statuses, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("deploymentId", deploymentId);
        params.put("statuses", resolveCaseStatuses(statuses));
        params.put("entities", collectUserAuthInfo());
        applyQueryContext(params, queryContext);
        applyDeploymentFilter(params);
        List<CaseInstance> processInstances =  commandService.execute(new QueryNameCommand<List<CaseInstance>>("getCaseInstancesByDeployment", params));

        return processInstances;
    }

    @Override
    public Collection<CaseInstance> getCaseInstancesByDefinition(String definitionId, List<CaseStatus> statuses, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("definitionId", definitionId);
        params.put("statuses", resolveCaseStatuses(statuses));
        params.put("entities", collectUserAuthInfo());
        applyQueryContext(params, queryContext);
        applyDeploymentFilter(params);
        List<CaseInstance> processInstances =  commandService.execute(new QueryNameCommand<List<CaseInstance>>("getCaseInstancesByDefinition", params));

        return processInstances;
    }

    @Override
    public Collection<CaseInstance> getCaseInstancesOwnedBy(String owner, List<CaseStatus> statuses, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("owner", owner);
        params.put("statuses", resolveCaseStatuses(statuses));
        applyQueryContext(params, queryContext);
        applyDeploymentFilter(params);
        List<CaseInstance> processInstances =  commandService.execute(new QueryNameCommand<List<CaseInstance>>("getCaseInstancesOwnedBy", params));

        return processInstances;
    }

    @Override
    public Collection<CaseInstance> getCaseInstancesByRole(String roleName, List<CaseStatus> statuses, QueryContext queryContext) {

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("roleName", roleName);
        params.put("entities", collectUserAuthInfo());
        params.put("statuses", resolveCaseStatuses(statuses));
        applyQueryContext(params, queryContext);
        applyDeploymentFilter(params);
        List<CaseInstance> processInstances =  commandService.execute(new QueryNameCommand<List<CaseInstance>>("getCaseInstancesByRole", params));

        return processInstances;
    }

    @Override
    public Collection<CaseInstance> getCaseInstancesAnyRole(List<CaseStatus> statuses, QueryContext queryContext) {

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("entities", collectUserAuthInfo());
        params.put("statuses", resolveCaseStatuses(statuses));
        applyQueryContext(params, queryContext);
        applyDeploymentFilter(params);
        List<CaseInstance> processInstances =  commandService.execute(new QueryNameCommand<List<CaseInstance>>("getCaseInstancesAnyRole", params));

        return processInstances;
    }

    @Override
    public Collection<CaseInstance> getCaseInstancesByDateItem(String dataItemName, List<CaseStatus> statuses, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("itemName", dataItemName);
        params.put("entities", collectUserAuthInfo());
        params.put("statuses", resolveCaseStatuses(statuses));
        applyQueryContext(params, queryContext);
        applyDeploymentFilter(params);
        List<CaseInstance> processInstances =  commandService.execute(new QueryNameCommand<List<CaseInstance>>("getCaseInstancesByVariableName", params));

        return processInstances;
    }

    @Override
    public Collection<CaseInstance> getCaseInstancesByDateItemAndValue(String dataItemName, String dataItemValue, List<CaseStatus> statuses, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("itemName", dataItemName);
        params.put("itemValue", dataItemValue);
        params.put("entities", collectUserAuthInfo());
        params.put("statuses", resolveCaseStatuses(statuses));
        applyQueryContext(params, queryContext);
        applyDeploymentFilter(params);
        List<CaseInstance> processInstances =  commandService.execute(new QueryNameCommand<List<CaseInstance>>("getCaseInstancesByVariableNameAndValue", params));

        return processInstances;
    }

    @Override
    public CaseInstance getCaseInstanceById(String caseId) {

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("correlationKey", caseId);
        params.put("maxResults", 1);

        List<CaseInstance> processInstances =  commandService.execute(new QueryNameCommand<List<CaseInstance>>("getCaseInstanceById", params));
        if (!processInstances.isEmpty()) {
            return processInstances.get(0);
        }

        throw new CaseNotFoundException("Case " + caseId + " was not found");
    }

    @Override
    public Collection<AdHocFragment> getAdHocFragmentsForCase(String caseId) {
        ProcessInstanceDesc pi = runtimeDataService.getProcessInstanceByCorrelationKey(correlationKeyFactory.newCorrelationKey(caseId));
        if (pi == null || !pi.getState().equals(ProcessInstance.STATE_ACTIVE)) {
            throw new CaseNotFoundException("No case instance found with id " + caseId + " or it's not active anymore");
        }

        CaseDefinition caseDef = getCase(pi.getDeploymentId(), pi.getProcessId());
        List<AdHocFragment> adHocFragments = new ArrayList<>();
        adHocFragments.addAll(caseDef.getAdHocFragments());

        Collection<CaseStageInstance> activeStages = internalGetCaseStages(caseDef, caseId, true, new QueryContext(0, 100));
        activeStages.forEach(stage -> adHocFragments.addAll(stage.getAdHocFragments()));

        return adHocFragments;
    }

    /*
     * Task related queries
     */

    @Override
    public List<TaskSummary> getCaseTasksAssignedAsPotentialOwner(String caseId, String userId, List<Status> status, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("caseId", caseId + "%");
        params.put("userId", userId);
        params.put("status", adoptList(status, allActiveStatus));
        params.put("groupIds", getAuthenticatedUserRoles(identityProvider));
        applyQueryContext(params, queryContext);
        List<TaskSummary> tasks =  commandService.execute(new QueryNameCommand<List<TaskSummary>>("getCaseTasksAsPotentialOwner", params));
        return tasks;
    }

    @Override
    public List<TaskSummary> getCaseTasksAssignedAsBusinessAdmin(String caseId, String userId, List<Status> status, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("caseId", caseId + "%");
        params.put("userId", userId);
        params.put("status", adoptList(status, allActiveStatus));
        params.put("groupIds", getAuthenticatedUserRoles(identityProvider));
        applyQueryContext(params, queryContext);
        List<TaskSummary> tasks =  commandService.execute(new QueryNameCommand<List<TaskSummary>>("getCaseTasksAsBusinessAdmin", params));
        return tasks;
    }

    @Override
    public List<TaskSummary> getCaseTasksAssignedAsStakeholder(String caseId, String userId, List<Status> status, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("caseId", caseId + "%");
        params.put("userId", userId);
        params.put("status", adoptList(status, allActiveStatus));
        params.put("groupIds", getAuthenticatedUserRoles(identityProvider));
        applyQueryContext(params, queryContext);
        List<TaskSummary> tasks =  commandService.execute(new QueryNameCommand<List<TaskSummary>>("getCaseTasksAsStakeholder", params));
        return tasks;
    }

    /*
     * Helper methods to parse process and extract case related information
     */

    public List<CaseStageInstance> internalGetCaseStages(CaseDefinition caseDef, String caseId, boolean activeOnly, QueryContext queryContext) {

        CorrelationKey correlationKey = correlationKeyFactory.newCorrelationKey(caseId);
        Collection<org.jbpm.services.api.model.NodeInstanceDesc> nodes = runtimeDataService.getNodeInstancesByCorrelationKeyNodeType(correlationKey,
                                                                                Arrays.asList(ProcessInstance.STATE_ACTIVE),
                                                                                Arrays.asList("DynamicNode"),
                                                                                queryContext);
        Collection<Long> completedNodes = nodes.stream().filter(n -> ((NodeInstanceDesc)n).getType() == 1).map(n -> n.getId()).collect(toList());

        Map<String, CaseStage> stagesByName = caseDef.getCaseStages().stream()
        .collect(toMap(CaseStage::getId, c -> c));
        Predicate<org.jbpm.services.api.model.NodeInstanceDesc> filterNodes = null;
        if (activeOnly) {

            filterNodes = n -> ((NodeInstanceDesc)n).getType() == 0 && !completedNodes.contains(((NodeInstanceDesc)n).getId());
        } else {
            filterNodes = n -> ((NodeInstanceDesc)n).getType() == 0;
        }

        List<String> triggeredStages = new ArrayList<>();
        List<CaseStageInstance> stages = new ArrayList<>();
        nodes.stream()
        .filter(filterNodes)
        .map(n -> {
            StageStatus status = StageStatus.Active;
            if (completedNodes.contains(((NodeInstanceDesc)n).getId())) {
                status = StageStatus.Completed;
            }
            Collection<org.jbpm.services.api.model.NodeInstanceDesc> activeNodes = getActiveNodesForCaseAndStage(caseId, n.getNodeId(), new QueryContext(0, 100));
            return new CaseStageInstanceImpl(n.getNodeId(), n.getName(), stagesByName.get(n.getNodeId()).getAdHocFragments(), activeNodes, status);
            })
        .forEach(csi -> {
            stages.add(csi);
            triggeredStages.add(csi.getName());
        });

        if (!activeOnly) {
            // add other stages that are present in the definition
            caseDef.getCaseStages().stream()
            .filter(cs -> !triggeredStages.contains(cs.getName()))
            .map(cs -> new CaseStageInstanceImpl(cs.getId(), cs.getName(), cs.getAdHocFragments(), Collections.emptyList(), StageStatus.Available))
            .forEach(csi -> stages.add(csi));
        }

        return stages;
    }

    protected Collection<org.jbpm.services.api.model.NodeInstanceDesc> getActiveNodesForCaseAndStage(String caseId, String stageId, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("caseId", caseId + "%");
        params.put("nodeContainerId", stageId);
        applyQueryContext(params, queryContext);
        applyDeploymentFilter(params);
        List<org.jbpm.services.api.model.NodeInstanceDesc> nodeInstances =  commandService.execute(new QueryNameCommand<List<org.jbpm.services.api.model.NodeInstanceDesc>>("getActiveNodesForCaseAndStage", params));
        return nodeInstances;
    }

    private Collection<CaseRole> collectCaseRoles(Process process) {

        String roles = (String) process.getMetaData().get("customCaseRoles");
        if (roles == null) {
            return Collections.emptyList();
        }
        List<CaseRole> result = new ArrayList<CaseRole>();
        String[] roleStrings = roles.split(",");
        for (String roleString: roleStrings) {
            String[] elements = roleString.split(":");
            CaseRoleImpl role = new CaseRoleImpl(elements[0]);
            result.add(role);
            if (elements.length > 1) {
                role.setCardinality(Integer.parseInt(elements[1]));
            }
        }
        return result;
    }

    private String collectCaseIdPrefix(Process process) {
        String caseIdPrefix = (String) process.getMetaData().get("customCaseIdPrefix");
        if (caseIdPrefix == null) {
            return CaseDefinition.DEFAULT_PREFIX;
        }

        return caseIdPrefix;
    }

    private Collection<CaseMilestone> collectMilestoness(Process process) {
        Collection<CaseMilestone> result = new ArrayList<CaseMilestone>();
        getMilestones((WorkflowProcess) process, result);

        return result;
    }

    private void getMilestones(NodeContainer container, Collection<CaseMilestone> result) {
        for (Node node: container.getNodes()) {
            if (node instanceof MilestoneNode) {
                result.add(new CaseMilestoneImpl((String) node.getMetaData().get("UniqueId"), node.getName(), ((MilestoneNode) node).getConstraint(), false));
            }
            if (node instanceof NodeContainer) {
                getMilestones((NodeContainer) node, result);
            }
        }
    }

    private Collection<CaseStage> collectCaseStages(String deploymentId, String processId, NodeContainer process) {
        Collection<CaseStage> result = new ArrayList<CaseStage>();

        for (Node node : process.getNodes()) {
            if (node instanceof DynamicNode) {
                DynamicNode dynamicNode = (DynamicNode) node;
                Collection<AdHocFragment> adHocFragments = collectAdHocFragments(dynamicNode);

                result.add(new CaseStageImpl((String) ((DynamicNode) node).getMetaData("UniqueId"),
                                             node.getName(),
                                             adHocFragments));
            }
        }
        return result;
    }

    private Collection<AdHocFragment> collectAdHocFragments(NodeContainer process) {
        List<AdHocFragment> result = new ArrayList<AdHocFragment>();

        checkAdHoc(process, result);

        return result;
    }

    private void checkAdHoc(NodeContainer nodeContainer, List<AdHocFragment> result) {
        for (Node node : nodeContainer.getNodes()) {
            if (node instanceof StartNode || node instanceof BoundaryEventNode) {
                continue;
            }
            if (node.getIncomingConnections().isEmpty()) {
                result.add(new AdHocFragmentImpl(node.getName(), node.getClass().getSimpleName()));
            }
        }
    }

    protected void applyQueryContext(Map<String, Object> params, QueryContext queryContext) {
        if (queryContext != null) {
            params.put("firstResult", queryContext.getOffset());
            params.put("maxResults", queryContext.getCount());

            if (queryContext.getOrderBy() != null && !queryContext.getOrderBy().isEmpty()) {
                params.put(QueryManager.ORDER_BY_KEY, queryContext.getOrderBy());

                if (queryContext.isAscending()) {
                    params.put(QueryManager.ASCENDING_KEY, "true");
                } else {
                    params.put(QueryManager.DESCENDING_KEY, "true");
                }
            }
        }
    }

    protected void applyDeploymentFilter(Map<String, Object> params) {
        if (deploymentRolesManager != null) {
            List<String> deploymentIdForUser = deploymentRolesManager.getDeploymentsForUser(identityProvider);

            if (deploymentIdForUser != null && !deploymentIdForUser.isEmpty()) {
                params.put(FILTER, " log.externalId in (:deployments) ");
                params.put("deployments", deploymentIdForUser);
            }
        }
    }

    protected List<?> adoptList(List<?> source, List<?> values) {

        if (source == null || source.isEmpty()) {
            List<Object> data = new ArrayList<Object>();
            for (Object value : values) {
                data.add(value);
            }

            return data;
        }
        return source;
    }

    protected List<String> collectUserAuthInfo() {
        List<String> entities = new ArrayList<>();
        entities.add(identityProvider.getName());
        entities.addAll(getAuthenticatedUserRoles(identityProvider));

        // add special public role to allow to find cases that do not use case roles
        entities.add(AuthorizationManager.PUBLIC_GROUP);

        return entities;
    }

    protected <T> Collection<T> applyPagination(List<T> input, QueryContext queryContext) {
        if (queryContext != null) {
            int start = queryContext.getOffset();
            int end = start + queryContext.getCount();
            if (input.size() < start) {
                // no elements in given range
                return new ArrayList<T>();
            } else if (input.size() >= end) {
                return Collections.unmodifiableCollection(new ArrayList<T>(input.subList(start, end)));
            } else if (input.size() < end) {
                return Collections.unmodifiableCollection(new ArrayList<T>(input.subList(start, input.size())));
            }

        }

        return Collections.unmodifiableCollection(input);
    }

    protected List<Integer> resolveCaseStatuses(List<CaseStatus> caseStatusesList) {
        return caseStatusesList != null ? caseStatusesList.stream().map(event -> event.getId()).collect(Collectors.toList()) : null;
    }

    @Override
    public Collection<CaseFileItem> getCaseInstanceDataItems(String caseId, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("caseId", caseId);
        params.put("entities", collectUserAuthInfo());
        applyQueryContext(params, queryContext);
        List<CaseFileItem> caseFileItems = commandService.execute(new QueryNameCommand<List<CaseFileItem>>("getCaseInstanceDataItems", params));

        return caseFileItems;
    }

    @Override
    public Collection<CaseFileItem> getCaseInstanceDataItemsByName(String caseId, List<String> names, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("caseId", caseId);
        params.put("itemNames", names);
        params.put("entities", collectUserAuthInfo());
        applyQueryContext(params, queryContext);
        List<CaseFileItem> caseFileItems = commandService.execute(new QueryNameCommand<List<CaseFileItem>>("getCaseInstanceDataItemsByName", params));

        return caseFileItems;
    }

    @Override
    public Collection<CaseFileItem> getCaseInstanceDataItemsByType(String caseId, List<String> types, QueryContext queryContext) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("caseId", caseId);
        params.put("itemTypes", types);
        params.put("entities", collectUserAuthInfo());
        applyQueryContext(params, queryContext);
        List<CaseFileItem> caseFileItems = commandService.execute(new QueryNameCommand<List<CaseFileItem>>("getCaseInstanceDataItemsByType", params));

        return caseFileItems;
    }

}


text:
<?xml version="1.0" encoding="UTF-8" ?>
<class xmlns="http://xml.phpdox.net/src" full="Yaf_Session" namespace="" name="Yaf_Session">
  <implements name="Iterator" full="Iterator"/>
  <member name="_instance" static="false" visibility="protected">
    <default>null</default>
    <docblock>
      <description compact=""/>
    </docblock>
  </member>
  <member name="_session" static="false" visibility="protected">
    <default>null</default>
    <docblock>
      <description compact=""/>
    </docblock>
  </member>
  <member name="_started" static="false" visibility="protected">
    <default>null</default>
    <docblock>
      <description compact=""/>
    </docblock>
  </member>
  <method name="__clone" abstract="false" static="false" final="false">
    <docblock>
      <description compact="The __clone purpose"/>
      <return type="void"/>
    </docblock>
  </method>
  <constructor name="__construct" abstract="false" static="false" final="false">
    <docblock>
      <description compact="The __construct purpose"/>
      <return type="void"/>
    </docblock>
  </constructor>
  <method name="count" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The count purpose"/>
      <return type="void"/>
    </docblock>
  </method>
  <method name="current" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The current purpose"/>
      <return type="void"/>
    </docblock>
  </method>
  <method name="del" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The del purpose"/>
      <return type="void"/>
    </docblock>
    <parameter name="name" optional="false" byreference="false" type="string"/>
  </method>
  <method name="__get" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The __get purpose"/>
      <return type="void"/>
    </docblock>
    <parameter name="name" optional="false" byreference="false" type="string"/>
  </method>
  <method name="getInstance" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The getInstance purpose"/>
      <return type="void"/>
    </docblock>
  </method>
  <method name="has" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The has purpose"/>
      <return type="void"/>
    </docblock>
    <parameter name="name" optional="false" byreference="false" type="string"/>
  </method>
  <method name="__isset" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The __isset purpose"/>
      <return type="void"/>
    </docblock>
    <parameter name="name" optional="false" byreference="false" type="string"/>
  </method>
  <method name="key" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The key purpose"/>
      <return type="void"/>
    </docblock>
  </method>
  <method name="next" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The next purpose"/>
      <return type="void"/>
    </docblock>
  </method>
  <method name="offsetExists" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The offsetExists purpose"/>
      <return type="void"/>
    </docblock>
    <parameter name="name" optional="false" byreference="false" type="string"/>
  </method>
  <method name="offsetGet" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The offsetGet purpose"/>
      <return type="void"/>
    </docblock>
    <parameter name="name" optional="false" byreference="false" type="string"/>
  </method>
  <method name="offsetSet" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The offsetSet purpose"/>
      <return type="void"/>
    </docblock>
    <parameter name="name" optional="false" byreference="false" type="string"/>
    <parameter name="value" optional="false" byreference="false" type="string"/>
  </method>
  <method name="offsetUnset" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The offsetUnset purpose"/>
      <return type="void"/>
    </docblock>
    <parameter name="name" optional="false" byreference="false" type="string"/>
  </method>
  <method name="rewind" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The rewind purpose"/>
      <return type="void"/>
    </docblock>
  </method>
  <method name="__set" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The __set purpose"/>
      <return type="void"/>
    </docblock>
    <parameter name="name" optional="false" byreference="false" type="string"/>
    <parameter name="value" optional="false" byreference="false" type="string"/>
  </method>
  <method name="__sleep" abstract="false" static="false" final="false">
    <docblock>
      <description compact="The __sleep purpose"/>
      <return type="void"/>
    </docblock>
  </method>
  <method name="start" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The start purpose"/>
      <return type="void"/>
    </docblock>
  </method>
  <method name="__unset" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The __unset purpose"/>
      <return type="void"/>
    </docblock>
    <parameter name="name" optional="false" byreference="false" type="string"/>
  </method>
  <method name="valid" abstract="false" static="false" visibility="public" final="false">
    <docblock>
      <description compact="The valid purpose"/>
      <return type="void"/>
    </docblock>
  </method>
  <method name="__wakeup" abstract="false" static="false" final="false">
    <docblock>
      <description compact="The __wakeup purpose"/>
      <return type="void"/>
    </docblock>
  </method>
</class>


text:
package org.springframework.amqp.tutorials;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @author Gary Russell
 * @author Scott Deeg
 */
public class RabbitAmqpTutorialsRunner implements CommandLineRunner {

	@Value("${tutorial.client.duration:0}")
	private int duration;

	@Autowired
	private ConfigurableApplicationContext ctx;

	@Override
	public void run(String... arg0) throws Exception {
		System.out.println("Ready ... running for " + duration + "ms");
		Thread.sleep(duration);
		ctx.close();
	}

}


text:
package com.fishercoder;

import com.fishercoder.common.utils.CommonUtils;
import com.fishercoder.solutions._733;
import org.junit.BeforeClass;
import org.junit.Test;

public class _733Test {
    private static _733.Solution1 solution1;
    private static int[][] image;
    private static int[][] result;

    @BeforeClass
    public static void setup() {
        solution1 = new _733.Solution1();
    }

    @Test
    public void test1() {
        image = new int[][]{
                {1, 1, 1},
                {1, 1, 0},
                {1, 0, 1}
        };
        result = solution1.floodFill(image, 1, 1, 2);
        CommonUtils.print2DIntArray(result);
    }

    @Test
    public void test2() {
        image = new int[][]{
                {0, 0, 0},
                {0, 0, 0}
        };
        result = solution1.floodFill(image, 0, 0, 2);
        CommonUtils.print2DIntArray(result);
    }

}


text:
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

/*=============================================================================
	PrimitiveSceneProxy.h: Primitive scene proxy definition.
=============================================================================*/

#pragma once
#include "SceneView.h"
#include "PrimitiveUniformShaderParameters.h"
#include "PrimitiveViewRelevance.h"

// Forward declarations.
class FSimpleLightEntry;
class HHitProxy;
class FStaticPrimitiveDrawInterface;
class FPrimitiveSceneInfo;
class FLightSceneProxy;
class FLightSceneInfo;
class FPrimitiveDrawInterface;

/** Data for a simple dynamic light. */
class FSimpleLightEntry
{
public:
	FVector Color;
	float Radius;
	float Exponent;
	bool bAffectTranslucency;
};

/** Data for a simple dynamic light which could change per-view. */
class FSimpleLightPerViewEntry
{
public:
	FVector Position;
};

/**
* Index into the Per-view data for each instance.
* Most uses wont need to add > 1 per view data.
* This array will be the same size as InstanceData for uses that require per view data. Otherwise it will be empty.
*/
class FSimpleLightInstacePerViewIndexData
{
public:
	uint32 PerViewIndex : 31;
	uint32 bHasPerViewData;
};

/** Data pertaining to a set of simple dynamic lights */
class FSimpleLightArray
{
public:
	/** Data per simple dynamic light instance, independent of view */
	TArray<FSimpleLightEntry, TMemStackAllocator<>> InstanceData;
	/** Per-view data for each light */
	TArray<FSimpleLightPerViewEntry, TMemStackAllocator<>> PerViewData;
	/** Indices into the per-view data for each light. */
	TArray<FSimpleLightInstacePerViewIndexData, TMemStackAllocator<>> InstancePerViewDataIndices;

public:

	/**
	* Returns the per-view data for a simple light entry.
	* @param LightIndex - The index of the simple light
	* @param ViewIndex - The index of the view
	* @param NumViews - The number of views in the ViewFamily.
	*/
	inline const FSimpleLightPerViewEntry& GetViewDependentData(int32 LightIndex, int32 ViewIndex, int32 NumViews) const
	{
		// If InstanceData has an equal number of elements to PerViewData then all views share the same PerViewData.
		if (InstanceData.Num() == PerViewData.Num())
		{
			check(InstancePerViewDataIndices.Num() == 0);
			return PerViewData[LightIndex];
		}
		else
		{
			check(InstancePerViewDataIndices.Num() == InstanceData.Num());

			// Calculate per-view index.
			FSimpleLightInstacePerViewIndexData PerViewIndex = InstancePerViewDataIndices[LightIndex];
			const int32 PerViewDataIndex = PerViewIndex.PerViewIndex + ( PerViewIndex.bHasPerViewData ? ViewIndex : 0 );
			return PerViewData[PerViewDataIndex];
		}
	}
};

/** Information about a heightfield gathered by the renderer for heightfield lighting. */
class FHeightfieldComponentDescription
{
public:
	FVector4 HeightfieldScaleBias;
	FVector4 MinMaxUV;
	FMatrix LocalToWorld;
	FVector2D LightingAtlasLocation;
	FIntRect HeightfieldRect;

	int32 NumSubsections;
	FVector4 SubsectionScaleAndBias;

	FHeightfieldComponentDescription(const FMatrix& InLocalToWorld) :
		LocalToWorld(InLocalToWorld)
	{}
};

namespace EDrawDynamicFlags
{
	enum Type
	{
		ForceLowestLOD = 0x1
	};
}

/**
 * Encapsulates the data which is mirrored to render a UPrimitiveComponent parallel to the game thread.
 * This is intended to be subclassed to support different primitive types.
 */
class FPrimitiveSceneProxy
{
public:

	/** Initialization constructor. */
	ENGINE_API FPrimitiveSceneProxy(const UPrimitiveComponent* InComponent, FName ResourceName = NAME_None);

	/** Virtual destructor. */
	ENGINE_API virtual ~FPrimitiveSceneProxy();

	/**
	 * Updates selection for the primitive proxy. This simply sends a message to the rendering thread to call SetSelection_RenderThread.
	 * This is called in the game thread as selection is toggled.
	 * @param bInParentSelected - true if the parent actor is selected in the editor
 	 * @param bInIndividuallySelected - true if the component is selected in the editor directly
	 */
	void SetSelection_GameThread(const bool bInParentSelected, const bool bInIndividuallySelected=false);

	/**
	 * Updates hover state for the primitive proxy. This simply sends a message to the rendering thread to call SetHovered_RenderThread.
	 * This is called in the game thread as hover state changes
	 * @param bInHovered - true if the parent actor is hovered
	 */
	void SetHovered_GameThread(const bool bInHovered);

	/**
	 * Updates the hidden editor view visibility map on the game thread which just enqueues a command on the render thread
	 */
	void SetHiddenEdViews_GameThread( uint64 InHiddenEditorViews );

	/** @return True if the primitive is visible in the given View. */
	ENGINE_API bool IsShown(const FSceneView* View) const;

	/** @return True if the primitive is casting a shadow. */
	ENGINE_API bool IsShadowCast(const FSceneView* View) const;

	/** Helper for components that want to render bounds. */
	ENGINE_API void RenderBounds(FPrimitiveDrawInterface* PDI, const FEngineShowFlags& EngineShowFlags, const FBoxSphereBounds& Bounds, bool bRenderInEditor) const;

	/** Returns the LOD that the primitive will render at for this view. */
	virtual int32 GetLOD(const FSceneView* View) const { return INDEX_NONE; }

	/**
	 * Creates the hit proxies are used when DrawDynamicElements is called.
	 * Called in the game thread.
	 * @param OutHitProxies - Hit proxes which are created should be added to this array.
	 * @return The hit proxy to use by default for elements drawn by DrawDynamicElements.
	 */
	ENGINE_API virtual HHitProxy* CreateHitProxies(UPrimitiveComponent* Component,TArray<TRefCountPtr<HHitProxy> >& OutHitProxies);

	/**
	 * Draws the primitive's static elements.  This is called from the rendering thread once when the scene proxy is created.
	 * The static elements will only be rendered if GetViewRelevance declares static relevance.
	 * @param PDI - The interface which receives the primitive elements.
	 */
	virtual void DrawStaticElements(FStaticPrimitiveDrawInterface* PDI) {}

	/**
	 * Gathers the primitive's dynamic mesh elements.  This will only be called if GetViewRelevance declares dynamic relevance.
	 * This is called from the rendering thread for each set of views that might be rendered.
	 * Game thread state like UObjects must have their properties mirrored on the proxy to avoid race conditions.  The rendering thread must not dereference UObjects.
	 * The gathered mesh elements will be used multiple times, any memory referenced must last as long as the Collector (eg no stack memory should be referenced).
	 * This function should not modify the proxy but simply collect a description of things to render.  Updates to the proxy need to be pushed from game thread or external events.
	 *
	 * @param Views - the array of views to consider.  These may not exist in the ViewFamily.
	 * @param ViewFamily - the view family, for convenience
	 * @param VisibilityMap - a bit representing this proxy's visibility in the Views array
	 * @param Collector - gathers the mesh elements to be rendered and provides mechanisms for temporary allocations
	 */
	virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, class FMeshElementCollector& Collector) const {}

	/**
	 * Gets the boxes for sub occlusion queries
	 * @param View - the view the occlusion results are for
	 * @return pointer to the boxes, must remain valid until the queries are built
	 */
	virtual const TArray<FBoxSphereBounds>* GetOcclusionQueries(const FSceneView* View) const
	{
		return nullptr;
	}

	/**
	 * Gives the primitive the results of sub-occlusion-queries
	 * @param View - the view the occlusion results are for
	 * @param Results - visibility results, allocated from the scene allocator, so valid until the end of the frame
	 * @param NumResults - number of visibility bools
	 */
	virtual void AcceptOcclusionResults(const FSceneView* View, const bool* Results, int32 NumResults) {}

	/**
	 * Determines the relevance of this primitive's elements to the given view.
	 * Called in the rendering thread.
	 * @param View - The view to determine relevance for.
	 * @return The relevance of the primitive's elements to the view.
	 */
	ENGINE_API virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View);

	/** Callback from the renderer to gather simple lights that this proxy wants renderered. */
	virtual void GatherSimpleLights(const FSceneViewFamily& ViewFamily, FSimpleLightArray& OutParticleLights) const {}

	/**
	 *	Determines the relevance of this primitive's elements to the given light.
	 *	@param	LightSceneProxy			The light to determine relevance for
	 *	@param	bDynamic (output)		The light is dynamic for this primitive
	 *	@param	bRelevant (output)		The light is relevant for this primitive
	 *	@param	bLightMapped (output)	The light is light mapped for this primitive
	 */
	virtual void GetLightRelevance(const FLightSceneProxy* LightSceneProxy, bool& bDynamic, bool& bRelevant, bool& bLightMapped, bool& bShadowMapped) const
	{
		// Determine the lights relevance to the primitive.
		bDynamic = true;
		bRelevant = true;
		bLightMapped = false;
		bShadowMapped = false;
	}

	virtual void GetDistancefieldAtlasData(FBox& LocalVolumeBounds, FIntVector& OutBlockMin, FIntVector& OutBlockSize, bool& bOutBuiltAsIfTwoSided, bool& bMeshWasPlane, TArray<FMatrix>& ObjectLocalToWorldTransforms) const
	{
		LocalVolumeBounds = FBox(0);
		OutBlockMin = FIntVector(-1, -1, -1);
		OutBlockSize = FIntVector(0, 0, 0);
		bOutBuiltAsIfTwoSided = false;
		bMeshWasPlane = false;
	}

	virtual void GetDistanceFieldInstanceInfo(int32& NumInstances, float& BoundsSurfaceArea) const
	{
		NumInstances = 0;
		BoundsSurfaceArea = 0;
	}

	virtual void GetHeightfieldRepresentation(UTexture2D*& OutHeightmapTexture, UTexture2D*& OutDiffuseColorTexture, FHeightfieldComponentDescription& OutDescription)
	{
		OutHeightmapTexture = NULL;
	}

	/**
	 *	Called when the rendering thread adds the proxy to the scene.
	 *	This function allows for generating renderer-side resources.
	 *	Called in the rendering thread.
	 */
	virtual void CreateRenderThreadResources() {}

	/**
	 * Called by the rendering thread to notify the proxy when a light is no longer
	 * associated with the proxy, so that it can clean up any cached resources.
	 * @param Light - The light to be removed.
	 */
	virtual void OnDetachLight(const FLightSceneInfo* Light)
	{
	}

	/**
	 * Called to notify the proxy when its transform has been updated.
	 * Called in the thread that owns the proxy; game or rendering.
	 */
	virtual void OnTransformChanged()
	{
	}

	/**
	 * Called to notify the proxy when its actor position has been updated.
	 * Called in the thread that owns the proxy; game or rendering.
	 */
	virtual void OnActorPositionChanged() {}

	/**
	 * Called to notify the proxy that the level has been fully added to
	 * the world and the primitive will now be rendered.
	 * Only called if bNeedsLevelAddedToWorldNotification is set to true.
	 */
	virtual void OnLevelAddedToWorld() {}

	/**
	* @return true if the proxy can be culled when occluded by other primitives
	*/
	virtual bool CanBeOccluded() const
	{
		return true;
	}

	/**
	* @return true if the proxy has custom occlusion queries
	*/
	virtual bool HasSubprimitiveOcclusionQueries() const
	{
		return false;
	}

	virtual bool ShowInBSPSplitViewmode() const
	{
		return false;
	}

	/**
	 * Determines the DPG to render the primitive in regardless of view.
	 * Should only be called if HasViewDependentDPG()==true.
	 */
	virtual uint8 GetStaticDepthPriorityGroup() const
	{
		check(!HasViewDependentDPG());
		return StaticDepthPriorityGroup;
	}

	/**
	 * Determines the DPG to render the primitive in for the given view.
	 * May be called regardless of the result of HasViewDependentDPG.
	 * @param View - The view to determine the primitive's DPG for.
	 * @return The DPG the primitive should be rendered in for the given view.
	 */
	uint8 GetDepthPriorityGroup(const FSceneView* View) const
	{
		return (bUseViewOwnerDepthPriorityGroup && IsOwnedBy(View->ViewActor)) ?
			ViewOwnerDepthPriorityGroup :
			StaticDepthPriorityGroup;
	}

	/** Every derived class should override these functions */
	virtual uint32 GetMemoryFootprint( void ) const = 0;
	uint32 GetAllocatedSize( void ) const { return( Owners.GetAllocatedSize() ); }

	/**
	 * Set the collision flag on the scene proxy to enable/disable collision drawing
	 *
	 * @param const bool bNewEnabled new state for collision drawing
	 */
	void SetCollisionEnabled_GameThread(const bool bNewEnabled);

	/**
	 * Set the collision flag on the scene proxy to enable/disable collision drawing (RENDER THREAD)
	 *
	 * @param const bool bNewEnabled new state for collision drawing
	 */
	void SetCollisionEnabled_RenderThread(const bool bNewEnabled);

	// Accessors.
	inline FSceneInterface& GetScene() const { return *Scene; }
	inline FPrimitiveComponentId GetPrimitiveComponentId() const { return PrimitiveComponentId; }
	inline FPrimitiveSceneInfo* GetPrimitiveSceneInfo() const { return PrimitiveSceneInfo; }
	inline const FMatrix& GetLocalToWorld() const { return LocalToWorld; }
	inline bool IsLocalToWorldDeterminantNegative() const { return bIsLocalToWorldDeterminantNegative; }
	inline const FBoxSphereBounds& GetBounds() const { return Bounds; }
	inline const FBoxSphereBounds& GetLocalBounds() const { return LocalBounds; }
	inline FName GetOwnerName() const { return OwnerName; }
	inline FName GetResourceName() const { return ResourceName; }
	inline FName GetLevelName() const { return LevelName; }
	FORCEINLINE TStatId GetStatId() const
	{
		return StatId;
	}
	inline float GetMinDrawDistance() const { return MinDrawDistance; }
	inline float GetMaxDrawDistance() const { return MaxDrawDistance; }
	inline int32 GetVisibilityId() const { return VisibilityId; }
	inline int16 GetTranslucencySortPriority() const { return TranslucencySortPriority; }
	inline bool HasMotionBlurVelocityMeshes() const { return bHasMotionBlurVelocityMeshes; }
	inline bool IsMovable() const { return !IsStatic(); }
	inline bool IsOftenMoving() const { return bOftenMoving; }
	inline bool IsStatic() const { return bStatic; }
	inline bool IsSelectable() const { return bSelectable; }
	inline bool IsParentSelected() const { return bParentSelected; }
	inline bool IsIndividuallySelected() const { return bIndividuallySelected; }
	inline bool IsSelected() const { return IsParentSelected() || IsIndividuallySelected(); }
	inline bool ShouldRenderCustomDepth() const { return bRenderCustomDepth; }
	inline uint8 GetCustomDepthStencilValue() const { return CustomDepthStencilValue; }
	inline bool ShouldRenderInMainPass() const { return bRenderInMainPass; }
	inline bool IsCollisionEnabled() const { return bCollisionEnabled; }
	inline bool IsHovered() const { return bHovered; }
	inline bool IsOwnedBy(const AActor* Actor) const { return Owners.Find(Actor) != INDEX_NONE; }
	inline bool HasViewDependentDPG() const { return bUseViewOwnerDepthPriorityGroup; }
	inline bool HasStaticLighting() const { return bStaticLighting; }
	inline bool NeedsUnbuiltPreviewLighting() const { return bNeedsUnbuiltPreviewLighting; }
	inline bool CastsStaticShadow() const { return bCastStaticShadow; }
	inline bool CastsDynamicShadow() const { return bCastDynamicShadow; }
	inline bool AffectsDynamicIndirectLighting() const { return bAffectDynamicIndirectLighting; }
	inline bool AffectsDistanceFieldLighting() const { return bAffectDistanceFieldLighting; }
	inline float GetLpvBiasMultiplier() const { return LpvBiasMultiplier; }
	inline EIndirectLightingCacheQuality GetIndirectLightingCacheQuality() const { return IndirectLightingCacheQuality; }
	inline bool CastsVolumetricTranslucentShadow() const { return bCastVolumetricTranslucentShadow; }
	inline bool CastsHiddenShadow() const { return bCastHiddenShadow; }
	inline bool CastsShadowAsTwoSided() const { return bCastShadowAsTwoSided; }
	inline bool CastsSelfShadowOnly() const { return bSelfShadowOnly; }
	inline bool CastsInsetShadow() const { return bCastInsetShadow; }
	inline bool CastsCinematicShadow() const { return bCastCinematicShadow; }
	inline bool CastsFarShadow() const { return bCastFarShadow; }
	inline bool LightAsIfStatic() const { return bLightAsIfStatic; }
	inline bool LightAttachmentsAsGroup() const { return bLightAttachmentsAsGroup; }
	inline bool StaticElementsAlwaysUseProxyPrimitiveUniformBuffer() const { return bStaticElementsAlwaysUseProxyPrimitiveUniformBuffer; }
	inline bool ShouldUseAsOccluder() const { return bUseAsOccluder; }
	inline bool AllowApproximateOcclusion() const { return bAllowApproximateOcclusion; }
	inline const TUniformBuffer<FPrimitiveUniformShaderParameters>& GetUniformBuffer() const { return UniformBuffer; }
	inline bool HasPerInstanceHitProxies () const { return bHasPerInstanceHitProxies; }
	inline bool UseEditorCompositing(const FSceneView* View) const { return GIsEditor && bUseEditorCompositing && !View->bIsGameView; }
	inline const FVector& GetActorPosition() const { return ActorPosition; }
	inline const bool ReceivesDecals() const { return bReceivesDecals; }
	inline bool WillEverBeLit() const { return bWillEverBeLit; }
	inline bool HasValidSettingsForStaticLighting() const { return bHasValidSettingsForStaticLighting; }
	inline bool AlwaysHasVelocity() const { return bAlwaysHasVelocity; }
	inline bool UseEditorDepthTest() const { return bUseEditorDepthTest; }
	inline bool SupportsDistanceFieldRepresentation() const { return bSupportsDistanceFieldRepresentation; }
	inline bool SupportsHeightfieldRepresentation() const { return bSupportsHeightfieldRepresentation; }
	inline bool TreatAsBackgroundForOcclusion() const { return bTreatAsBackgroundForOcclusion; }
	inline bool NeedsLevelAddedToWorldNotification() const { return bNeedsLevelAddedToWorldNotification; }
	inline bool IsComponentLevelVisible() const { return bIsComponentLevelVisible; }
	inline bool IsStaticPathAvailable() const { return !bDisableStaticPath; }

#if WITH_EDITOR
	inline int32 GetNumUncachedStaticLightingInteractions() { return NumUncachedStaticLightingInteractions; }

	void SetHierarchicalLOD_GameThread(const int32 InLODLevel);
	void SetHierarchicalLOD_RenderThread(const int32 InLODLevel);
#endif

	inline FLinearColor GetWireframeColor() const { return WireframeColor; }
	inline FLinearColor GetLevelColor() const { return LevelColor; }
	inline FLinearColor GetPropertyColor() const { return PropertyColor; }

	/**
	* Returns whether this proxy should be considered a "detail mesh".
	* Detail meshes are distance culled even if distance culling is normally disabled for the view. (e.g. in editor)
	*/
	virtual bool IsDetailMesh() const
	{
		return false;
	}

	/**
	 *	Returns whether the proxy utilizes custom occlusion bounds or not
	 *
	 *	@return	bool		true if custom occlusion bounds are used, false if not;
	 */
	virtual bool HasCustomOcclusionBounds() const
	{
		return false;
	}

	/**
	 *	Return the custom occlusion bounds for this scene proxy.
	 *
	 *	@return	FBoxSphereBounds		The custom occlusion bounds.
	 */
	virtual FBoxSphereBounds GetCustomOcclusionBounds() const
	{
		checkf(false, TEXT("GetCustomOcclusionBounds> Should not be called on base scene proxy!"));
		return GetBounds();
	}

	virtual bool HasDistanceFieldRepresentation() const
	{
		return false;
	}

	/**
	 * Drawing helper. Draws nice bouncy line.
	 */
	static ENGINE_API void DrawArc(FPrimitiveDrawInterface* PDI, const FVector& Start, const FVector& End, const float Height, const uint32 Segments, const FLinearColor& Color
		, uint8 DepthPriorityGroup,	const float Thickness = 0.0f, const bool bScreenSpace = false);

	static ENGINE_API void DrawArrowHead(FPrimitiveDrawInterface* PDI, const FVector& Tip, const FVector& Origin, const float Size, const FLinearColor& Color
		, uint8 DepthPriorityGroup,	const float Thickness = 0.0f, const bool bScreenSpace = false);

	/**
	 * Shifts primitive position and all relevant data by an arbitrary delta.
	 * Called on world origin changes
	 * @param InOffset - The delta to shift by
	 */
	ENGINE_API virtual void ApplyWorldOffset(FVector InOffset);

	/**
	 * Updates the primitive proxy's uniform buffer.
	 */
	ENGINE_API void UpdateUniformBuffer();

protected:

	/** Allow subclasses to override the primitive name. Used primarily by BSP. */
	void OverrideOwnerName(FName InOwnerName)
	{
		OwnerName = InOwnerName;
	}

	FLinearColor WireframeColor;
	FLinearColor LevelColor;
	FLinearColor PropertyColor;

private:
	friend class FScene;

	uint32 bIsLocalToWorldDeterminantNegative : 1;
	uint32 DrawInGame : 1;
	uint32 DrawInEditor : 1;
	uint32 bReceivesDecals : 1;
	uint32 bOnlyOwnerSee : 1;
	uint32 bOwnerNoSee : 1;
	uint32 bStatic : 1;
	uint32 bOftenMoving : 1;
	/** Parent Actor is selected */
	uint32 bParentSelected : 1;
	/** Component is selected directly */
	uint32 bIndividuallySelected : 1;

	/** true if the mouse is currently hovered over this primitive in a level viewport */
	uint32 bHovered : 1;

	/** true if ViewOwnerDepthPriorityGroup should be used. */
	uint32 bUseViewOwnerDepthPriorityGroup : 1;

	/** true if the primitive has motion blur velocity meshes */
	uint32 bHasMotionBlurVelocityMeshes : 1;

	/** DPG this prim belongs to. */
	uint32 StaticDepthPriorityGroup : SDPG_NumBits;

	/** DPG this primitive is rendered in when viewed by its owner. */
	uint32 ViewOwnerDepthPriorityGroup : SDPG_NumBits;

	/** True if the primitive will cache static lighting. */
	uint32 bStaticLighting : 1;

	/** If true this primitive Renders in the mainPass */
	uint32 bRenderInMainPass : 1;

	/** If true this primitive will render only after owning level becomes visible */
	uint32 bRequiresVisibleLevelToRender : 1;

	/** Whether component level is currently visible */
	uint32 bIsComponentLevelVisible : 1;

	/** Whether this component has any collision enabled */
	uint32 bCollisionEnabled : 1;

	/** Whether the primitive should be treated as part of the background for occlusion purposes. */
	uint32 bTreatAsBackgroundForOcclusion : 1;

	friend class FLightPrimitiveInteraction;
	/** Whether the renderer needs us to temporarily use only the dynamic drawing path */
	uint32 bDisableStaticPath : 1;
protected:

	/** Whether the primitive should be statically lit but has unbuilt lighting, and a preview should be used. */
	uint32 bNeedsUnbuiltPreviewLighting : 1;

	/** True if the primitive wants to use static lighting, but has invalid content settings to do so. */
	uint32 bHasValidSettingsForStaticLighting : 1;

	/** Can be set to false to skip some work only needed on lit primitives. */
	uint32 bWillEverBeLit : 1;

	/** True if the primitive casts dynamic shadows. */
	uint32 bCastDynamicShadow : 1;

	/** True if the primitive casts Reflective Shadow Map shadows (meaning it affects Light Propagation Volumes). */
	uint32 bAffectDynamicIndirectLighting : 1;

	uint32 bAffectDistanceFieldLighting : 1;

	/** True if the primitive casts static shadows. */
	uint32 bCastStaticShadow : 1;

	/**
	 * Whether the object should cast a volumetric translucent shadow.
	 * Volumetric translucent shadows are useful for primitives with smoothly changing opacity like particles representing a volume,
	 * But have artifacts when used on highly opaque surfaces.
	 */
	uint32 bCastVolumetricTranslucentShadow : 1;

	/** True if the primitive casts shadows even when hidden. */
	uint32 bCastHiddenShadow : 1;

	/** Whether this primitive should cast dynamic shadows as if it were a two sided material. */
	uint32 bCastShadowAsTwoSided : 1;

	/** When enabled, the component will only cast a shadow on itself and not other components in the world.  This is especially useful for first person weapons, and forces bCastInsetShadow to be enabled. */
	uint32 bSelfShadowOnly : 1;

	/** Whether this component should create a per-object shadow that gives higher effective shadow resolution. true if bSelfShadowOnly is true. */
	uint32 bCastInsetShadow : 1;

	/**
	 * Whether this component should create a per-object shadow that gives higher effective shadow resolution.
	 * Useful for cinematic character shadowing. Assumed to be enabled if bSelfShadowOnly is enabled.
	 */
	uint32 bCastCinematicShadow : 1;

	/* When enabled, the component will be rendering into the distant shadow cascades (only for directional lights). */
	uint32 bCastFarShadow : 1;

	/**
	 * This has to be known by the rendering thread to avoid marking lighting dirty when new interactions are created,
	 * Which happens when a movable mesh with bLightAsIfStatic moves into the influence of a light it was not baked against.
	 */
	uint32 bLightAsIfStatic : 1;

	/**
	 * Whether to light this component and any attachments as a group.  This only has effect on the root component of an attachment tree.
	 * When enabled, attached component shadowing settings like bCastInsetShadow, bCastVolumetricTranslucentShadow, etc, will be ignored.
	 * This is useful for improving performance when multiple movable components are attached together.
	 */
	uint32 bLightAttachmentsAsGroup : 1;

	/**
	 * Whether this proxy always uses UniformBuffer and no other uniform buffers.
	 * When true, a fast path for updating can be used that does not update static draw lists.
	 */
	uint32 bStaticElementsAlwaysUseProxyPrimitiveUniformBuffer : 1;

	/** Whether the primitive should always be considered to have velocities, even if it hasn't moved. */
	uint32 bAlwaysHasVelocity : 1;

	/** Whether editor compositing depth testing should be used for this primitive.  Only matters for primitives with bUseEditorCompositing. */
	uint32 bUseEditorDepthTest : 1;

	/** Whether the primitive type supports a distance field representation.  Does not mean the primitive has a valid representation. */
	uint32 bSupportsDistanceFieldRepresentation : 1;

	/** Whether the primitive implements GetHeightfieldRepresentation() */
	uint32 bSupportsHeightfieldRepresentation : 1;

	/** Whether this primitive requires notification when its level is added to the world and made visible for the first time. */
	uint32 bNeedsLevelAddedToWorldNotification : 1;

private:

	/** If this is True, this primitive will be used to occlusion cull other primitives. */
	uint32 bUseAsOccluder:1;

	/** If this is True, this primitive doesn't need exact occlusion info. */
	uint32 bAllowApproximateOcclusion : 1;

	/** If this is True, this primitive can be selected in the editor. */
	uint32 bSelectable : 1;

	/** If this primitive has per-instance hit proxies. */
	uint32 bHasPerInstanceHitProxies : 1;

	/** Whether this primitive should be composited onto the scene after post processing (editor only) */
	uint32 bUseEditorCompositing : 1;

	/** This primitive has bRenderCustomDepth enabled */
	uint32 bRenderCustomDepth : 1;

	/** Optionally write this stencil value during the CustomDepth pass */
	uint8 CustomDepthStencilValue;

protected:
	/** The bias applied to LPV injection */
	float LpvBiasMultiplier;

	/** Quality of interpolated indirect lighting for Movable components. */
	EIndirectLightingCacheQuality IndirectLightingCacheQuality;

private:
	/** The primitive's local to world transform. */
	FMatrix LocalToWorld;

	/** The primitive's bounds. */
	FBoxSphereBounds Bounds;

	/** The primitive's local space bounds. */
	FBoxSphereBounds LocalBounds;

	/** The component's actor's position. */
	FVector ActorPosition;

	/** The hierarchy of owners of this primitive.  These must not be dereferenced on the rendering thread, but the pointer values can be used for identification.  */
	TArray<const AActor*> Owners;

	/** The scene the primitive is in. */
	FSceneInterface* Scene;

	/**
	 * Id for the component this proxy belongs to.
	 * This will stay the same for the lifetime of the component, so it can be used to identify the component across re-registers.
	 */
	FPrimitiveComponentId PrimitiveComponentId;

	/** Pointer back to the PrimitiveSceneInfo that owns this Proxy. */
	FPrimitiveSceneInfo* PrimitiveSceneInfo;

	/** The name of the actor this component is attached to. */
	FName OwnerName;

	/** The name of the resource used by the component. */
	FName ResourceName;

	/** The name of the level the primitive is in. */
	FName LevelName;

#if WITH_EDITOR
	/** A copy of the actor's group membership for handling per-view group hiding */
	uint64 HiddenEditorViews;
#endif

	/** The translucency sort priority */
	int16 TranslucencySortPriority;

	/** Used for precomputed visibility */
	int32 VisibilityId;

	/** Used for dynamic stats */
	TStatId StatId;

	/** The primitive's cull distance. */
	float MaxDrawDistance;

	/** The primitive's minimum cull distance. */
	float MinDrawDistance;

	/** The primitive's uniform buffer. */
	TUniformBuffer<FPrimitiveUniformShaderParameters> UniformBuffer;

	/**
	 * The UPrimitiveComponent this proxy is for, useful for quickly inspecting properties on the corresponding component while debugging.
	 * This should not be dereferenced on the rendering thread.  The game thread can be modifying UObject members at any time.
	 * Use PrimitiveComponentId instead when a component identifier is needed.
	 */
	const UPrimitiveComponent* ComponentForDebuggingOnly;

#if WITH_EDITOR
	/**
	*	How many invalid lights for this primitive, just refer for scene outliner
	*/
	int32 NumUncachedStaticLightingInteractions;

	/** this is used if world setting has EnableHierarchical LOD true */
	int32 HierarchicalLODOverride;
#endif

	/** Updates the proxy's actor position, called from the game thread. */
	ENGINE_API void UpdateActorPosition(FVector InActorPosition);

	/**
	 * Updates the primitive proxy's cached transforms, and calls OnUpdateTransform to notify it of the change.
	 * Called in the thread that owns the proxy; game or rendering.
	 * @param InLocalToWorld - The new local to world transform of the primitive.
	 * @param InBounds - The new bounds of the primitive.
	 * @param InLocalBounds - The local space bounds of the primitive.
	 */
	ENGINE_API void SetTransform(const FMatrix& InLocalToWorld, const FBoxSphereBounds& InBounds, const FBoxSphereBounds& InLocalBounds, FVector InActorPosition);

	/**
	 * Either updates the uniform buffer or defers it until it becomes visible depending on a cvar
	 */
	ENGINE_API void UpdateUniformBufferMaybeLazy();

	/** Updates the hidden editor view visibility map on the render thread */
	void SetHiddenEdViews_RenderThread( uint64 InHiddenEditorViews );

protected:
	/** Updates selection for the primitive proxy. This is called in the rendering thread by SetSelection_GameThread. */
	void SetSelection_RenderThread(const bool bInParentSelected, const bool bInIndividuallySelected);

	/** Updates hover state for the primitive proxy. This is called in the rendering thread by SetHovered_GameThread. */
	void SetHovered_RenderThread(const bool bInHovered);
};