text:
package fi.uta.fsd.metka.storage.repository.impl;

import fi.uta.fsd.Logger;
import fi.uta.fsd.metka.enums.*;
import fi.uta.fsd.metka.model.access.calls.ValueDataFieldCall;
import fi.uta.fsd.metka.model.access.enums.StatusCode;
import fi.uta.fsd.metka.model.configuration.*;
import fi.uta.fsd.metka.model.data.RevisionData;
import fi.uta.fsd.metka.model.data.change.ValueChange;
import fi.uta.fsd.metka.model.data.container.*;
import fi.uta.fsd.metka.model.data.value.Value;
import fi.uta.fsd.metka.model.general.ApproveInfo;
import fi.uta.fsd.metka.model.general.DateTimeUserPair;
import fi.uta.fsd.metka.model.transfer.TransferData;
import fi.uta.fsd.metka.model.transfer.TransferField;
import fi.uta.fsd.metka.model.transfer.TransferRow;
import fi.uta.fsd.metka.model.transfer.TransferValue;
import fi.uta.fsd.metka.names.Fields;
import fi.uta.fsd.metka.storage.cascade.CascadeInstruction;
import fi.uta.fsd.metka.storage.cascade.Cascader;
import fi.uta.fsd.metka.storage.repository.*;
import fi.uta.fsd.metka.storage.repository.enums.ReturnResult;
import fi.uta.fsd.metka.storage.repository.enums.SerializationResults;
import fi.uta.fsd.metka.storage.response.OperationResponse;
import fi.uta.fsd.metka.storage.response.RevisionableInfo;
import fi.uta.fsd.metka.storage.restrictions.RestrictionValidator;
import fi.uta.fsd.metka.storage.restrictions.ValidateResult;
import fi.uta.fsd.metka.storage.util.JSONUtil;
import fi.uta.fsd.metkaAmqp.Messenger;
import fi.uta.fsd.metkaAmqp.payloads.*;
import fi.uta.fsd.metkaSearch.SearcherComponent;
import fi.uta.fsd.metkaSearch.commands.searcher.expert.ExpertRevisionSearchCommand;
import fi.uta.fsd.metkaSearch.results.ResultList;
import fi.uta.fsd.metkaSearch.results.RevisionResult;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

// TODO: at the moment does mostly DEFAULT language approval for restrictions
@Repository
public class RevisionApproveRepositoryImpl implements RevisionApproveRepository {

    @Autowired
    private ConfigurationRepository configurations;

    @Autowired
    private RevisionRepository revisions;

    @Autowired
    private JSONUtil json;

    @Autowired
    private RevisionRemoveRepository remove;

    @Autowired
    private RestrictionValidator validator;

    @Autowired
    private Cascader cascader;

    @Autowired
    private Messenger messenger;

    @Autowired
    private SearcherComponent searcher;

    @Autowired
    private RevisionEditRepository edit;

    @Autowired
    private RevisionSaveRepository save;

    @Autowired
    private EhCacheCacheManager cacheManager;

    @Override
    public Pair<OperationResponse, TransferData> approve(TransferData transferData, DateTimeUserPair info) {
        if(info == null) {
            info = DateTimeUserPair.build();
        }

        Pair<ReturnResult, RevisionData> dataPair = revisions.getRevisionData(transferData.getKey().getId().toString());
        if(dataPair.getLeft() != ReturnResult.REVISION_FOUND) {
            Logger.error(getClass(), "No revision to approve for " + transferData.getKey().toString());
            return new ImmutablePair<>(OperationResponse.build(dataPair.getLeft()), transferData);
        }

        Pair<ReturnResult, Configuration> configPair = configurations.findConfiguration(transferData.getConfiguration());
        if(configPair.getLeft() != ReturnResult.CONFIGURATION_FOUND) {
            Logger.error(getClass(), "Can't find configuration "+transferData.getConfiguration().toString()+" and so halting approval process.");
            return new ImmutablePair<>(OperationResponse.build(dataPair.getLeft()), transferData);
        }

        Configuration configuration = configPair.getRight();

        RevisionData data = dataPair.getRight();
        if(data.getState() != RevisionState.DRAFT) {
            // Still do cascade since there could be drafts under this revision
            for(Operation operation : configuration.getCascade()) {
                if(!(operation.getType() == OperationType.APPROVE || operation.getType() == OperationType.ALL)) {
                    continue;
                }
                cascader.cascade(CascadeInstruction.build(OperationType.APPROVE, info), data, operation.getTargets(), configuration);
            }

            Logger.info(getClass(), "Can't approve revision "+data.getKey().toString()+" since it is not in DRAFT state");
            // Fetch the data again since cascade might have changed things
            dataPair = revisions.getRevisionData(transferData.getKey().getId().toString());
            if(dataPair.getLeft() != ReturnResult.REVISION_FOUND) {
                Logger.error(getClass(), "No revision to approve for " + transferData.getKey().toString());
                return new ImmutablePair<>(OperationResponse.build(dataPair.getLeft()), transferData);
            }
            data = dataPair.getRight();
            if(data.getState() != RevisionState.DRAFT) {
                return new ImmutablePair<>(OperationResponse.build(ReturnResult.REVISION_NOT_A_DRAFT), transferData);
            }
        }

        // Do validation
        for(Operation operation : configuration.getRestrictions()) {
            if(!(operation.getType() == OperationType.APPROVE || operation.getType() == OperationType.ALL)) {
                continue;
            }
            ValidateResult vr = validator.validate(data, operation.getTargets(), configuration);
            if(!vr.getResult()) {
                return new ImmutablePair<>(
                        OperationResponse.build(vr),
                        transferData);
            }
        }

        ReturnResult result = ReturnResult.OPERATION_SUCCESSFUL;

        // Do cascade
        for(Operation operation : configuration.getCascade()) {
            Logger.debug(this.getClass(),"Cascading operation " + operation.getType() + " for " + transferData.getKey().getId().toString());
            if(!(operation.getType() == OperationType.APPROVE || operation.getType() == OperationType.ALL)) {
                continue;
            }
            if(!cascader.cascade(CascadeInstruction.build(OperationType.APPROVE, info), data, operation.getTargets(), configuration)) {
                result = ReturnResult.CASCADE_FAILURE;
            }
        }
        // If cascade fails then don't approve this revision
        if(result != ReturnResult.OPERATION_SUCCESSFUL) {
            return new ImmutablePair<>(OperationResponse.build(result), transferData);
        }

        // Fetch the data again since cascade might have changed things
        dataPair = revisions.getRevisionData(transferData.getKey().getId().toString());
        if(dataPair.getLeft() != ReturnResult.REVISION_FOUND) {
            Logger.error(getClass(), "No revision to approve for " + transferData.getKey().toString());
            return new ImmutablePair<>(OperationResponse.build(dataPair.getLeft()), transferData);
        }
        data = dataPair.getRight();
        if(data.getState() != RevisionState.DRAFT) {
            return new ImmutablePair<>(OperationResponse.build(ReturnResult.REVISION_NOT_A_DRAFT), transferData);
        }

        // TODO: Check that all SELECTION values are still valid (e.g. that they can be found and that the values are not marked deprecated
        // TODO: Check that other references like series are still valid (e.g. they point to existing revisionables

        // If validation was successful then check all languages that should be approved (i.e. which languages have content
        // that has changed in this revision).
        // If revision has no changed content for given language then that language doesn't need updated approval information.
        if(result == ReturnResult.OPERATION_SUCCESSFUL) {
            if (data.getConfiguration().getType().equals(ConfigurationType.STUDY)) {
                ReferenceContainerDataField files = (ReferenceContainerDataField) data.getField(Fields.FILES);
                String approvedFiles = "";
                if (files != null) {
                    for (ReferenceRow file : files.getReferences()) {
                        Pair<ReturnResult, RevisionableInfo> attachmentInfo = revisions.getRevisionableInfo(Long.parseLong(file.getReference().getValue().split("-")[0]));
                        if (!attachmentInfo.getLeft().equals(ReturnResult.REVISIONABLE_FOUND)) {
                            continue;
                        }
                        if (!attachmentInfo.getRight().getRemoved() && !approvedFiles.contains(file.getReference().getValue().split("-")[0])) {
                            if (!approvedFiles.equals("")) {
                                approvedFiles += ",";
                            }
                            approvedFiles += file.getReference().getValue().split("-")[0];
                        }
                    }
                }
                data.putChange(new ValueChange(Fields.APPROVED_FILES));
                if (data.getField(Fields.APPROVED_FILES) != null) {
                    ((ValueDataField) data.getField(Fields.APPROVED_FILES)).setCurrentFor(Language.DEFAULT, new ValueContainer(null, new Value(approvedFiles)));
                } else {
                    data.getFields().put(Fields.APPROVED_FILES, new ValueDataField(Fields.APPROVED_FILES));
                    ((ValueDataField) data.getField(Fields.APPROVED_FILES)).setCurrentFor(Language.DEFAULT, new ValueContainer(null, new Value(approvedFiles)));
                }
            }
            Set<Language> changesIn = hasChanges(data, configuration);

            // No changes in this revision, remove it instead
            if(changesIn.isEmpty() && transferData.getState().getSaved() == null) {
                remove.removeDraft(transferData.getKey(), info);
                return new ImmutablePair<>(OperationResponse.build(ReturnResult.NO_CHANGES), transferData);
            }

            for(Language language : changesIn) {
                data.approveRevision(language, new ApproveInfo(data.getKey().getNo(), info));
            }

            // Do final operations before saving data to database
            result = finalizeApproval(data, configuration, info);
            if(result != ReturnResult.OPERATION_SUCCESSFUL) {
                return new ImmutablePair<>(OperationResponse.build(result), transferData);
            }

            data.setState(RevisionState.APPROVED);
            data.setLatest("approved");
            data.setHandler("");
            Pair<SerializationResults, String> string = json.serialize(data);
            if(string.getLeft() != SerializationResults.SERIALIZATION_SUCCESS) {
                Logger.error(getClass(), "Couldn't serialize data "+data.toString()+", halting approval process");
                return new ImmutablePair<>(OperationResponse.build(ReturnResult.OPERATION_FAIL), transferData);
            }
            Pair<ReturnResult, RevisionableInfo> infoPair = revisions.getRevisionableInfo(data.getKey().getId());
            if (infoPair.getLeft().equals(ReturnResult.REVISIONABLE_FOUND)){
                Pair<ReturnResult, RevisionData> oldLatestPair = revisions.getRevisionData(data.getKey().getId(), infoPair.getRight().getApproved());
                if (oldLatestPair.getLeft().equals(ReturnResult.REVISION_FOUND)){
                    RevisionData oldLatestData = oldLatestPair.getRight();
                    oldLatestData.setLatest("false");
                    revisions.updateRevisionData(oldLatestData);
                }
            }
            ReturnResult updateResult = revisions.updateRevisionData(data);

            if(updateResult != ReturnResult.REVISION_UPDATE_SUCCESSFUL) {
                return new ImmutablePair<>(OperationResponse.build(updateResult), transferData);
            }

            messenger.sendAmqpMessage(messenger.FD_APPROVE, new RevisionPayload(data));
            //revisions.indexRevision(data.getKey());

            // We need to clear the cache in order to keep cache vs db integrity over large transactions.
            cacheManager.getCache("revision-cache").clear();

            return new ImmutablePair<>(OperationResponse.build(ReturnResult.OPERATION_SUCCESSFUL), TransferData.buildFromRevisionData(data, RevisionableInfo.FALSE));
        } else {
            return new ImmutablePair<>(OperationResponse.build(result), transferData);
        }
    }

    /**
     * This does operations that have to be done just before revision can be saved to database.
     * These operations should be such that they can not fail and that they can not affect any other data.
     * @param revision    RevisionData to be finalized
     */
    private ReturnResult finalizeApproval(RevisionData revision, Configuration configuration, DateTimeUserPair info) {
        // Check if any fields were removed from the configuration
        Map<String, DataField> newFields = new HashMap<>();
        for (DataField field : revision.getFields().values()){
            if (configuration.getField(field.getKey()) != null){
                newFields.put(field.getKey(), field);
            }
        }
        revision.getFields().clear();
        revision.getFields().putAll(newFields);
        switch(revision.getConfiguration().getType()) {
            case STUDY:
                return finalizeStudyApproval(revision, info);
            case STUDY_ERROR:
                finalizeStudyErrorApproval(revision, configuration);
                return ReturnResult.OPERATION_SUCCESSFUL;
            case PUBLICATION:
                return finalizePublicationApproval(revision, info);
            default:
                return ReturnResult.OPERATION_SUCCESSFUL;
        }
    }

    /**
     * Checks that if there are approved languages that don't yet have aipcomplete date then inserts
     * that approval time to aipcomplete for that language;
     * @param revision    RevisionData to be finalized
     */
    private ReturnResult finalizeStudyApproval(RevisionData revision, DateTimeUserPair info) {
        if(info == null) {
            info = DateTimeUserPair.build();
        }
        Pair<StatusCode, ValueDataField> aipcompletePair = revision.dataField(ValueDataFieldCall.get("aipcomplete"));
        for(Language language : Language.values()) {
            if(revision.isApprovedFor(language)) {
                // We have approved value for this language, check if it's missing from aipcomplete
                if(aipcompletePair.getLeft() != StatusCode.FIELD_FOUND || !aipcompletePair.getRight().hasValueFor(language)) {
                    messenger.sendAmqpMessage(messenger.FB_AIP, new AipCompletePayload(revision, language, "", info.getTime().toString()));
                    aipcompletePair = revision.dataField(ValueDataFieldCall
                            .set("aipcomplete", new Value(new LocalDate(revision.approveInfoFor(language).getApproved().getTime()).toString()), language)
                            .setInfo(info)
                            .setChangeMap(revision.getChanges()));
                }
            }
        }

        if(revision.getChange(Fields.DATAVERSIONS) != null || revision.getChange(Fields.DESCVERSIONS) != null) {
            messenger.sendAmqpMessage(messenger.FB_VERSION_CHANGES, new VersionChangePayload(revision));
        }

        return ReturnResult.OPERATION_SUCCESSFUL;
    }

    /**
     * Special case check for study errors.
     * Checks that if stidy related to study error has combined error score of >= 10
     * then sends a AMQP-message about that
     * @param revision StudyError revision data
     * @return Always returns OPERATION_SUCCESSFUL
     */
    private void finalizeStudyErrorApproval(RevisionData revision, Configuration configuration) {
        revisions.sendStudyErrorMessageIfNeeded(revision, configuration);
    }

    /**
     * Special case check for publications.
     * Handles descversions of studies related to the approved publication.
     * @param revision StudyError revision data
     * @return Always returns OPERATION_SUCCESSFUL
     */
    private ReturnResult finalizePublicationApproval(RevisionData revision, DateTimeUserPair info) {
        List<Long> handled = new ArrayList<>();
        // Iterate through related studies
        ReferenceContainerDataField studies = (ReferenceContainerDataField) revision.getField("studies");
        for (ReferenceRow reference : studies.getReferences()){
            if (!handled.contains(Long.parseLong(reference.getActualValue()))) {
                Pair<ReturnResult, RevisionData> studyPair = revisions.getRevisionData(reference.getActualValue());
                if (!studyPair.getLeft().equals(ReturnResult.REVISION_FOUND)){
                    continue;
                }
                handleStudyPublication(studyPair.getRight(), revision, info);
                handled.add(studyPair.getRight().getKey().getId());
            }
        }

        // Iterate through related series
        ReferenceContainerDataField series = (ReferenceContainerDataField) revision.getField("series");
        for (ReferenceRow reference : series.getReferences()){
            Pair<ReturnResult, RevisionData> seriesPair = revisions.getRevisionData(reference.getReference().getValue());
            if (!seriesPair.getLeft().equals(ReturnResult.REVISION_FOUND)){
                continue;
            }
            // Query for studies with the found series
            ExpertRevisionSearchCommand command = null;
            try {
                command = ExpertRevisionSearchCommand.build("+key.configuration.type:STUDY +series:"+reference.getReference().getValue()+" +state.removed:FALSE", configurations);
            } catch (QueryNodeException e) {
                continue;
            }
            ResultList<RevisionResult> seriesStudiesResult = searcher.executeSearch(command);
            for (RevisionResult result: seriesStudiesResult.getResults()){
                if (!handled.contains(result.getId())){
                    Pair<ReturnResult, RevisionData> studyPair = revisions.getRevisionData(result.getId().toString());
                    if (!studyPair.getLeft().equals(ReturnResult.REVISION_FOUND)){
                        continue;
                    }
                    handleStudyPublication(studyPair.getRight(), revision, info);
                    handled.add(studyPair.getRight().getKey().getId());
                }
            }
        }
        return ReturnResult.OPERATION_SUCCESSFUL;
    }

    /**
     * Handles a study linked to the publication to be approved. This includes adding the missing reference
     * and raising the descversion by 0.1.
     * If the study is APPROVED, create a new DRAFT, handle the revision and approve the revision.
     * if the study is already a DRAFT, only handle the revision and save.
     * @param revision RevisionData of the study linked to the publication
     * @param publication RevisionData of the publication being approved
     * @param info Date and User information for the ongoing publication approval operation.
     */
    private void handleStudyPublication(RevisionData revision, RevisionData publication, DateTimeUserPair info){
        Pair<ReturnResult, RevisionableInfo> infoPair = revisions.getRevisionableInfo(revision.getKey().getId());
        if (!infoPair.getLeft().equals(ReturnResult.REVISIONABLE_FOUND)){
            return;
        }
        if (revision.getState().equals(RevisionState.DRAFT)){
            TransferData transferData = TransferData.buildFromRevisionData(revision, infoPair.getRight());
            TransferField descversions = null;
            if (transferData.hasField("descversions")){
                descversions = transferData.getField("descversions");
            } else {
                descversions = new TransferField("descversions", TransferFieldType.CONTAINER);
                transferData.getFields().put("descversions", descversions);
            }
            TransferRow newRow = new TransferRow("descversions");

            TransferField newField = new TransferField("versionlabeldesc", TransferFieldType.VALUE);
            newField.getValues().put(Language.DEFAULT, new TransferValue());
            newField.getValueFor(Language.DEFAULT).setCurrent("23");
            newRow.addField(newField);

            newField = new TransferField("versionpro", TransferFieldType.VALUE);
            newField.getValues().put(Language.DEFAULT, new TransferValue());
            newField.getValueFor(Language.DEFAULT).setCurrent(info.getUser());
            newRow.addField(newField);

            Double newVersionNo = 0.0;
            Double currVersionNo;
            if (descversions.hasRows()) {
                for (TransferRow row : descversions.getRows().get(Language.DEFAULT)) {
                    if (row.getField("descversion") == null){
                        continue;
                    }
                    try {
                        currVersionNo = Double.parseDouble(row.getField("descversion").getValueFor(Language.DEFAULT).getValue());
                    } catch (NumberFormatException ex) {
                        currVersionNo = 1.0;
                    }
                    if (currVersionNo > newVersionNo) {
                        newVersionNo = currVersionNo;
                    }
                }
            }
            newVersionNo = newVersionNo + 0.1;
            newField = new TransferField("descversion", TransferFieldType.VALUE);
            newField.getValues().put(Language.DEFAULT, new TransferValue());
            newField.getValueFor(Language.DEFAULT).setCurrent(BigDecimal.valueOf(newVersionNo).setScale(1, RoundingMode.DOWN).toString());
            newRow.addField(newField);

            newField = new TransferField("versiondate", TransferFieldType.VALUE);
            newField.getValues().put(Language.DEFAULT, new TransferValue());
            newField.getValueFor(Language.DEFAULT).setCurrent(info.getTime().toString(DateTimeFormat.forPattern("yyyy-MM-dd")));
            newRow.addField(newField);

            descversions.addRowFor(Language.DEFAULT, newRow);

            Boolean referenceExists = false;
            // Add the publication reference to the study
            TransferField publications = transferData.getField("publications");
            if (publications == null){
                publications = new TransferField("publications", TransferFieldType.REFERENCECONTAINER);
                transferData.addField(publications);
            } else {
                for (TransferRow row : publications.getRowsFor(Language.DEFAULT)) {
                    if (row.getValue().equals(publication.getKey().getId().toString())) {
                        referenceExists = true;
                    }
                }
            }
            if (!referenceExists){
                TransferRow newPublicationRow = new TransferRow("publications");
                newPublicationRow.setValue(publication.getKey().getId().toString());
                publications.addRowFor(Language.DEFAULT, newPublicationRow);
            }
            save.saveRevision(transferData, info);
        } else if (revision.getState().equals(RevisionState.APPROVED)) {
            Pair<OperationResponse, RevisionData> editPair = edit.edit(revision.getKey(), info);
            TransferData transferData = TransferData.buildFromRevisionData(editPair.getRight(), infoPair.getRight());
            TransferField descversions = null;
            if (transferData.hasField("descversions")){
                descversions = transferData.getField("descversions");
            } else {
                descversions = new TransferField("descversions", TransferFieldType.CONTAINER);
                transferData.getFields().put("descversions", descversions);
            }
            TransferRow newRow = new TransferRow("descversions");

            TransferField newField = new TransferField("versionlabeldesc", TransferFieldType.VALUE);
            newField.getValues().put(Language.DEFAULT, new TransferValue());
            newField.getValueFor(Language.DEFAULT).setCurrent("23");
            newRow.addField(newField);

            newField = new TransferField("versionpro", TransferFieldType.VALUE);
            newField.getValues().put(Language.DEFAULT, new TransferValue());
            newField.getValueFor(Language.DEFAULT).setCurrent(info.getUser());
            newRow.addField(newField);

            Double newVersionNo = 0.0;
            Double currVersionNo;
            if (descversions.hasRows()) {
                for (TransferRow row : descversions.getRows().get(Language.DEFAULT)) {
                    if (row.getField("descversion") == null){
                        continue;
                    }
                    try {
                        currVersionNo = Double.parseDouble(row.getField("descversion").getValueFor(Language.DEFAULT).getValue());
                    } catch (NumberFormatException ex) {
                        currVersionNo = 1.0;
                    }
                    if (currVersionNo > newVersionNo) {
                        newVersionNo = currVersionNo;
                    }
                }
            }
            newVersionNo = newVersionNo + 0.1;
            newField = new TransferField("descversion", TransferFieldType.VALUE);
            newField.getValues().put(Language.DEFAULT, new TransferValue());
            newField.getValueFor(Language.DEFAULT).setCurrent(BigDecimal.valueOf(newVersionNo).setScale(1, RoundingMode.DOWN).toString());
            newRow.addField(newField);

            newField = new TransferField("versiondate", TransferFieldType.VALUE);
            newField.getValues().put(Language.DEFAULT, new TransferValue());
            newField.getValueFor(Language.DEFAULT).setCurrent(info.getTime().toString(DateTimeFormat.forPattern("yyyy-MM-dd")));
            newRow.addField(newField);

            descversions.addRowFor(Language.DEFAULT, newRow);

            Boolean referenceExists = false;
            // Add the publication reference to the study
            TransferField publications = transferData.getField("publications");
            if (publications == null){
                publications = new TransferField("publications", TransferFieldType.REFERENCECONTAINER);
                transferData.addField(publications);
            } else {
                for (TransferRow row : publications.getRowsFor(Language.DEFAULT)) {
                    if (row.getValue().equals(publication.getKey().getId().toString())) {
                        referenceExists = true;
                    }
                }
            }
            if (!referenceExists){
                TransferRow newPublicationRow = new TransferRow("publications");
                newPublicationRow.setValue(publication.getKey().getId().toString());
                publications.addRowFor(Language.DEFAULT, newPublicationRow);
            }
            save.saveRevision(transferData, info);
            approve(transferData, info);
        }
    }

    /**
     * Checks RevisionData for changes in all languages and marks every language that contains changes.
     * Changes are detected only from terminating DataFields i.e. ValueDataFields and ReferenceContainerDataFields.
     * ContainerDataFields can't terminate sensibly and so we don't care about changes in those alone, there has
     * to always be a change in a terminating field within the Container.
     *
     * This process checks the actual fields for changes and does not rely on change map since definite data is needed.
     * ValueDataFields are checked for current value and reference containers are checked for unapproved rows.
     *
     * @param data             RevisionData to check for changes in languages
     * @param configuration    Configuration for RevisionData
     * @return Set containing all Languages that have changes from previous revision
     */
    private Set<Language> hasChanges(RevisionData data, Configuration configuration) {
        Set<Language> changesIn = new HashSet<>();
        for(DataField dataField : data.getFields().values()) {
            boolean missing = false;
            for(Language l : Language.values()) {
                if(!changesIn.contains(l)) {
                    missing = true;
                    break;
                }
            }
            if(!missing) {
                // We have a change in all languages, no point in continuing
                break;
            }

            if(dataField instanceof ContainerDataField) {
                checkContainerForChanges(changesIn, (ContainerDataField)dataField, configuration);
            } else {
                checkTerminatingFieldForChanges(changesIn, dataField, configuration);
            }
        }
        return changesIn;
    }

    private void checkContainerForChanges(Set<Language> changesIn, ContainerDataField container, Configuration configuration) {
        Field fieldConf = configuration.getField(container.getKey());
        if (fieldConf == null){
            return;
        }
        if(!fieldConf.getTranslatable()) {
            // Container is not translatable, check only DEFAULT rows
            checkContainerForChangesIn(changesIn, container, configuration, Language.DEFAULT);

        } else {
            // Container is translatable, check all rows we don't need to forward the language since configuration
            // has forced translatable true for all fields inside this container tree and so all languages will be checked anyway
            for(Language language : Language.values()) {
                if(changesIn.contains(language)) {
                    // We can skip the language since we know that all values inside the row will be of the given language
                    continue;
                }
                checkContainerForChangesIn(changesIn, container, configuration, language);
            }
        }

    }

    private void checkContainerForChangesIn(Set<Language> changesIn, ContainerDataField container, Configuration configuration, Language language) {
        if(!container.hasRowsFor(language)) {
            // No rows for given language, continue loop
            return;
        }
        for(DataRow row : container.getRowsFor(language)) {
            // We can shortcut some checks.
            // Unapproved rows and deleted rows are automatically changes in provided language.
            // We can set the change and then terminate the search later
            if(row.getUnapproved() || row.getRemoved()) {
                changesIn.add(language);
            }

            // Check only changed rows.
            for(DataField dataField : row.getFields().values()) {
                if(dataField instanceof ContainerDataField) {
                    checkContainerForChanges(changesIn, (ContainerDataField)dataField, configuration);
                } else {
                    checkTerminatingFieldForChanges(changesIn, dataField, configuration);
                }
            }
        }
    }

    private void checkTerminatingFieldForChanges(Set<Language> changesIn, DataField dataField, Configuration configuration) {
        if(dataField instanceof ReferenceContainerDataField) {
            checkReferenceContainerForChanges(changesIn, (ReferenceContainerDataField)dataField);
        } else {
            checkValueForChanges(changesIn, (ValueDataField)dataField, configuration);
        }
    }

    private void checkReferenceContainerForChanges(Set<Language> changesIn, ReferenceContainerDataField container) {
        // We're checking ReferenceContainerDataField
        // Reference containers are not translated and so we are only checking for changes in DEFAULT language.
        // Furthermore reference rows are not updatable and so the only change we are interested in is added or removed rows.
        // Rows that are added have property 'unapproved' set to true so we can check additions with this.
        // Rows that are removed are not copied to new revisions so removed rows also constitute a change

        if(changesIn.contains(Language.DEFAULT)) {
            // If there is already a marked change for default then we don't need to check further
            return;
        }

        for(ReferenceRow row : container.getReferences()) {
            // TODO: More reliable monitoring on reference changes?
            // We need to be able to revert back to a revision.
            // Therefore we need to be able to tell which reference targets were removed or approved
            // during which revision.
            //if(row.getUnapproved() || row.getRemoved()) {
                changesIn.add(Language.DEFAULT);
            //}
        }
    }

    /**
     * Checks single ValueDataField for changes and records all languages where changes have happened.
     * Uses change as a guide but checks all possible values for equality with original value before
     * deciding if change has taken place or not.
     * @param changesIn        Set for all languages that have changes
     * @param valueField       Value field object to check
     * @param configuration    Configuration
     */
    private void checkValueForChanges(Set<Language> changesIn, ValueDataField valueField, Configuration configuration) {
        Field fieldConf = configuration.getField(valueField.getKey());

        if (fieldConf == null) {
            //configuration error
            return;
        }

        if(!fieldConf.getTranslatable() && !changesIn.contains(Language.DEFAULT)) {
            // field is not translatable, no need to check other than DEFAULT
            checkValueForChangesIn(changesIn, valueField, Language.DEFAULT);
        } else {
            // Field is translatable, check all languages
            for(Language language : Language.values()) {
                if(changesIn.contains(language)) {
                    continue;
                }
                checkValueForChangesIn(changesIn, valueField, language);
            }
        }
    }

    /**
     * Checks given change and field for changes in given language and if change found marks it to given set.
     * If there's already a change for given language then no further checking is done in this method.
     * @param changesIn        Set for all languages that have changes
     * @param valueField            ValueDataField to check for changes
     * @param language         Language to check changes for
     */
    private void checkValueForChangesIn(Set<Language> changesIn, ValueDataField valueField, Language language) {
        if(valueField.hasCurrentFor(language) && !valueField.currentForEqualsOriginal(language)) {
            changesIn.add(language);
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
package com.bornstone.stonehenge.common.utils;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;

/**
 * 图片处理工具类,eg:图片缩放、添加水印等.
 *
 * @author leo
 *         email: leo3877@gmail.com
 *         weibo:  http://weibo.com/leo3877
 * @author
 * @date 2012-2-27下午2:25:45
 * @since 1.0.0
 */
public class ImageVarietyUtil {

    // 水印位置(无、左上、右上、居中、左下、右下)
    public enum WatermarkPosition {
        no, topLeft, topRight, center, bottomLeft, bottomRight
    }

    /**
     * 图片缩放(图片等比例缩放为指定大小,空白部分以白色填充)
     *
     * @param srcBufferedImage 源图片
     * @param destFile         缩放后的图片文件
     */
    public static void zoom(BufferedImage srcBufferedImage, File destFile, int destHeight, int destWidth) {
        try {
            int imgWidth = destWidth;
            int imgHeight = destHeight;
            int srcWidth = srcBufferedImage.getWidth();
            int srcHeight = srcBufferedImage.getHeight();
            if (srcHeight >= srcWidth) {
                imgWidth = (int) Math.round(((destHeight * 1.0 / srcHeight) * srcWidth));
            } else {
                imgHeight = (int) Math.round(((destWidth * 1.0 / srcWidth) * srcHeight));
            }
            BufferedImage destBufferedImage = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics2D = destBufferedImage.createGraphics();
            graphics2D.setBackground(Color.WHITE);
            graphics2D.clearRect(0, 0, destWidth, destHeight);
            graphics2D.drawImage(srcBufferedImage.getScaledInstance(imgWidth, imgHeight, Image.SCALE_SMOOTH), (destWidth / 2) - (imgWidth / 2), (destHeight / 2) - (imgHeight / 2), null);
            graphics2D.dispose();
            ImageIO.write(destBufferedImage, "JPEG", destFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加图片水印
     *
     * @param srcBufferedImage 需要处理的源图片
     * @param destFile         处理后的图片文件
     * @param watermarkFile    水印图片文件
     */
    public static void imageWatermark(BufferedImage srcBufferedImage, File destFile, File watermarkFile, WatermarkPosition watermarkPosition, int alpha) {
        try {
            int srcWidth = srcBufferedImage.getWidth();
            int srcHeight = srcBufferedImage.getHeight();
            BufferedImage destBufferedImage = new BufferedImage(srcWidth, srcHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics2D = destBufferedImage.createGraphics();
            graphics2D.setBackground(Color.WHITE);
            graphics2D.clearRect(0, 0, srcWidth, srcHeight);
            graphics2D.drawImage(srcBufferedImage.getScaledInstance(srcWidth, srcHeight, Image.SCALE_SMOOTH), 0, 0, null);

            if (watermarkFile != null && watermarkFile.exists() && watermarkPosition != null && watermarkPosition != WatermarkPosition.no) {
                BufferedImage watermarkBufferedImage = ImageIO.read(watermarkFile);
                int watermarkImageWidth = watermarkBufferedImage.getWidth();
                int watermarkImageHeight = watermarkBufferedImage.getHeight();
                graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha / 100.0F));
                int x = 0;
                int y = 0;
                if (watermarkPosition == WatermarkPosition.topLeft) {
                    x = 0;
                    y = 0;
                } else if (watermarkPosition == WatermarkPosition.topRight) {
                    x = srcWidth - watermarkImageWidth;
                    y = 0;
                } else if (watermarkPosition == WatermarkPosition.center) {
                    x = (srcWidth - watermarkImageWidth) / 2;
                    y = (srcHeight - watermarkImageHeight) / 2;
                } else if (watermarkPosition == WatermarkPosition.bottomLeft) {
                    x = 0;
                    y = srcHeight - watermarkImageHeight;
                } else if (watermarkPosition == WatermarkPosition.bottomRight) {
                    x = srcWidth - watermarkImageWidth;
                    y = srcHeight - watermarkImageHeight;
                }
                graphics2D.drawImage(watermarkBufferedImage, x, y, watermarkImageWidth, watermarkImageHeight, null);
            }
            graphics2D.dispose();
            ImageIO.write(destBufferedImage, "JPEG", destFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 图片缩放并添加图片水印(图片等比例缩放为指定大小,空白部分以白色填充)
     *
     * @param srcBufferedImage 需要处理的图片
     * @param destFile         处理后的图片文件
     * @param watermarkFile    水印图片文件
     */
    public static void zoomAndWatermark(BufferedImage srcBufferedImage, File destFile, int destHeight, int destWidth, File watermarkFile, WatermarkPosition watermarkPosition, int alpha) {
        try {
            int imgWidth = destWidth;
            int imgHeight = destHeight;
            int srcWidth = srcBufferedImage.getWidth();
            int srcHeight = srcBufferedImage.getHeight();
            if (srcHeight >= srcWidth) {
                imgWidth = (int) Math.round(((destHeight * 1.0 / srcHeight) * srcWidth));
            } else {
                imgHeight = (int) Math.round(((destWidth * 1.0 / srcWidth) * srcHeight));
            }

            BufferedImage destBufferedImage = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics2D = destBufferedImage.createGraphics();
            graphics2D.setBackground(Color.WHITE);
            graphics2D.clearRect(0, 0, destWidth, destHeight);
            graphics2D.drawImage(srcBufferedImage.getScaledInstance(imgWidth, imgHeight, Image.SCALE_SMOOTH), (destWidth / 2) - (imgWidth / 2), (destHeight / 2) - (imgHeight / 2), null);

            if (watermarkFile != null && watermarkFile.exists() && watermarkPosition != null && watermarkPosition != WatermarkPosition.no) {
                BufferedImage watermarkBufferedImage = ImageIO.read(watermarkFile);
                int watermarkImageWidth = watermarkBufferedImage.getWidth();
                int watermarkImageHeight = watermarkBufferedImage.getHeight();
                graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha / 100.0F));
                int x = 0;
                int y = 0;
                if (watermarkPosition == WatermarkPosition.topLeft) {
                    x = 0;
                    y = 0;
                } else if (watermarkPosition == WatermarkPosition.topRight) {
                    x = destWidth - watermarkImageWidth;
                    y = 0;
                } else if (watermarkPosition == WatermarkPosition.center) {
                    x = (destWidth - watermarkImageWidth) / 2;
                    y = (destHeight - watermarkImageHeight) / 2;
                } else if (watermarkPosition == WatermarkPosition.bottomLeft) {
                    x = 0;
                    y = destHeight - watermarkImageHeight;
                } else if (watermarkPosition == WatermarkPosition.bottomRight) {
                    x = destWidth - watermarkImageWidth;
                    y = destHeight - watermarkImageHeight;
                }
                graphics2D.drawImage(watermarkBufferedImage, x, y, watermarkImageWidth, watermarkImageHeight, null);
            }
            graphics2D.dispose();
            ImageIO.write(destBufferedImage, "JPEG", destFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取图片文件的类型.
     *
     * @param imageFile 图片文件对象.
     * @return 图片文件类型
     */
    public static String getImageFormatName(File imageFile) {
        try {
            ImageInputStream imageInputStream = ImageIO.createImageInputStream(imageFile);
            Iterator<ImageReader> iterator = ImageIO.getImageReaders(imageInputStream);
            if (!iterator.hasNext()) {
                return null;
            }
            ImageReader imageReader = (ImageReader) iterator.next();
            imageInputStream.close();
            return imageReader.getFormatName().toLowerCase();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}


text:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/btn_danger_press" />
    <item android:drawable="@drawable/btn_danger" />
</selector>


text:
package org.mockito.exceptions;

@Deprecated
/**
 * @Deprecated. This class has been moved to internal packages because it was never meant to be public.
 * If you need it for extending Mockito please let us know. You can still use {@link org.mockito.internal.reporting.Discrepancy}.
 * However, the package clearly states that the class in a part of a public API so it can change.
 */
public class Discrepancy extends org.mockito.internal.reporting.Discrepancy {
    public Discrepancy(int wantedCount, int actualCount) {
        super(wantedCount, actualCount);
    }
}


text:
'use strict';

/* Controllers */

var ConversateApp = angular.module('conversate.controllers', []);
ConversateApp.controller('HomeController', ['$rootScope', '$scope', '$location', HomeController]);
ConversateApp.controller('ChatController', ['$rootScope', '$scope', '$location', 'ChatService', ChatController]);

function HomeController($rootScope, $scope, $location) {
	$scope.start = function() {
		$location.path('/chat');
	};
}

function ChatController($rootScope, $scope, $location, ChatService) {
	//$scope.chatOutput = '
Aakrit: Hello, how can I help you?
';
	$scope.chatOutput = '';

	$scope.chatKey = function(ev) {
	  if (ev.which==13)
	    $scope.chat();
	}

	$scope.chat = function() {
		var chatMessage = $scope.chatInput;
		$scope.chatOutput += '
' + chatMessage + '
';
    $scope.chatInput = '';

		$scope.chatData = ChatService.get({message: chatMessage, tags: $rootScope.tags}, function(data) {
				$scope.chatOutput += '
Bot: ' + data.response + '
';
				if(data.tags)
				{
					$rootScope.tags = data.tags;
				}
		  });
	}
}


text:
package com.azure.resourcemanager.machinelearning.generated;

import com.azure.core.credential.AccessToken;
import com.azure.core.http.HttpClient;
import com.azure.core.http.HttpHeaders;
import com.azure.core.http.HttpRequest;
import com.azure.core.http.HttpResponse;
import com.azure.core.http.rest.PagedIterable;
import com.azure.core.management.AzureEnvironment;
import com.azure.core.management.profile.AzureProfile;
import com.azure.core.util.Context;
import com.azure.resourcemanager.machinelearning.MachineLearningManager;
import com.azure.resourcemanager.machinelearning.models.CodeContainer;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public final class CodeContainersListMockTests {
    @Test
    public void testList() throws Exception {
        HttpClient httpClient = Mockito.mock(HttpClient.class);
        HttpResponse httpResponse = Mockito.mock(HttpResponse.class);
        ArgumentCaptor<HttpRequest> httpRequest = ArgumentCaptor.forClass(HttpRequest.class);

        String responseStr =
            "{\"value\":[{\"properties\":{\"isArchived\":false,\"latestVersion\":\"mazdfsqxh\",\"nextVersion\":\"mrejparnpvgr\",\"description\":\"rbwtdrcwgzwl\",\"properties\":{\"acfculzjrmhpf\":\"lhhfi\",\"xsoxi\":\"wvyldqpzf\"},\"tags\":{\"qqt\":\"jlzkdrocqsxy\"}},\"id\":\"iwdwisvnmeylajam\",\"name\":\"ajyhftpzc\",\"type\":\"ryklleynqa\"}]}";

        Mockito.when(httpResponse.getStatusCode()).thenReturn(200);
        Mockito.when(httpResponse.getHeaders()).thenReturn(new HttpHeaders());
        Mockito
            .when(httpResponse.getBody())
            .thenReturn(Flux.just(ByteBuffer.wrap(responseStr.getBytes(StandardCharsets.UTF_8))));
        Mockito
            .when(httpResponse.getBodyAsByteArray())
            .thenReturn(Mono.just(responseStr.getBytes(StandardCharsets.UTF_8)));
        Mockito
            .when(httpClient.send(httpRequest.capture(), Mockito.any()))
            .thenReturn(
                Mono
                    .defer(
                        () -> {
                            Mockito.when(httpResponse.getRequest()).thenReturn(httpRequest.getValue());
                            return Mono.just(httpResponse);
                        }));

        MachineLearningManager manager =
            MachineLearningManager
                .configure()
                .withHttpClient(httpClient)
                .authenticate(
                    tokenRequestContext -> Mono.just(new AccessToken("this_is_a_token", OffsetDateTime.MAX)),
                    new AzureProfile("", "", AzureEnvironment.AZURE));

        PagedIterable<CodeContainer> response =
            manager.codeContainers().list("aluzyi", "fcvcewbwq", "dgsjsat", Context.NONE);

        Assertions.assertEquals("rbwtdrcwgzwl", response.iterator().next().properties().description());
        Assertions.assertEquals("lhhfi", response.iterator().next().properties().properties().get("acfculzjrmhpf"));
        Assertions.assertEquals("jlzkdrocqsxy", response.iterator().next().properties().tags().get("qqt"));
        Assertions.assertEquals(false, response.iterator().next().properties().isArchived());
    }
}


text:
if [ "$(id -u)" == "0" ]; then
    echo "This script must not be run as su"
    exit 1
fi

cd ~/
mkdir -p repo/github
cd repo/github

# install what is essential
sudo apt-get install git git-core htop clang gdb build-essential cmake nmap cloc linux-tools &&

# install my custom stuff
git clone https://github.com/pdy/scripts.git &&
git clone https://github.com/pdy/dotfiles.git &&

sudo ./scripts/new_debian_helpers/guest_additions.sh
./scripts/vim/vim_from_src.sh
sudo ./repo/github/scripts/install.sh

cd ~/
./repo/github/scripts/vim/vundle_checkout.sh
./repo/github/dotfiles/install.sh


text:
title: Summary of questions for Wiley's course
author: Justin Ball
layout: post
permalink: "/2005/11/26/summary-of-questions-for-wileys-course/"
tags:
  - "School"
date: '2005-11-26T07:00:00Z'
templateKey: blog-post
path: "/summary-of-questions-for-wileys-course"
description: ''
---

Since I do try to share here is the list of questions for [Wiley's 7150 course][1]:

The Definition Debate

 [1]: http://opencontent.org/wiki/index.php?title=INST_7150_Syllabus_Fall_2005

1.  Should only things that are digital be counted as learning
    objects, or should a variety of other things be included, like people,
    places, and events?
2.  How important is the potential reusability of material in
    determining whether or not some content should be called a learning
    object?
3.  Does content need to be explicitly instructional in order to be called a learning object?

The Reusability Paradox

1.  How much context-related information should go in a learning object?
2.  What can the domain being taught suggest about how big a learning object should be?

Internal And External Context (No questions only vocabulary)

1.  internal context
2.  external context
3.  degree of suggestion
4.  fit

Things To Consider

1.  Why use learning objects?
2.  What are the costs of using learning objects that you may not immediately see?
3.  What are some scenarios in which the need for reuse seems to justify the cost and trouble of learning objects?

Anything or Automating?

1.  Should learning objects adhere to a common structure?

The Three Kinds Of Reuse

1.  What is the value of personalizing / repurposing learning objects
    relative to the direct costs of adapting each object and the
    opportunity cost of being able to scale up to huge number of learners
    if you don't have to touch each object?
2.  What are the impacts on learning if one doesn't repurpose for alignment with other objects?
3.  Are there types of repurposing other than academic, cultural, and technical adaptation that we should consider?
4.  Is there ever a time when it's just cheaper or faster to develop your own materials, rather than repurposing an existing object

Learning Object Metaphors

1.  What do the various metaphors that have been used to characterize
    learning objects tell us about how they can and cannot be reused?

Automated Assembly of Learning Objects

1.  What are some of the different ways that content can be stored /
    represented with an eye toward automating the reuse process? Can you
    think of new ones?
2.  What are some of the different ways that learning objects can be automatically reused? Can you think of new ones?

The Sixth Sense Effect

1.  What is the Sixth Sense effect? What are the risks of automated
    systems described by the effect? What are possible ways around the
    effect?
2.  What is the role of social interaction in the context of systems that automatically assemble learning objects for learner use?

Singing In The Rain

1.  In the brick-and-mortar metaphor of learning objects use, what
    factors go in to making a good mortar, and in building a useful brick
    structure? How do you create meaningful context?
2.  Is creating a meaningful context for learning object reuse
    any different from creating a meaningful context for reusing other
    educational materials, like book chapters or research articles?

Content Strategy And Discourse Objects

1.  Why do we restrict our thinking about learning objects to content? What
    other kinds of learning objects could exist within the context of
    digital, reusable, and supporting learning?


text:
<?php

namespace ThreadAndMirror\MoodBoardBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class ThreadAndMirrorMoodBoardBundle extends Bundle
{
}


text:
module Tools
  module Utils

  end
end


text:
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ProjectModuleManager">
    <modules>
      <module fileurl="file://$PROJECT_DIR$/.idea/modules/java-project.iml" filepath="$PROJECT_DIR$/.idea/modules/java-project.iml" />
      <module fileurl="file://$PROJECT_DIR$/.idea/modules/java-project_main.iml" filepath="$PROJECT_DIR$/.idea/modules/java-project_main.iml" group="java-project" />
      <module fileurl="file://$PROJECT_DIR$/.idea/modules/java-project_test.iml" filepath="$PROJECT_DIR$/.idea/modules/java-project_test.iml" group="java-project" />
    </modules>
  </component>
</project>


text:
@interface QLMSearchSecondPageTableViewController : UITableViewController<UISearchResultsUpdating>

@end


text:
extern NSString * __nonnull const NBErrorDomain;
extern NSInteger const NBErrorCodeInvalidArgument;

// Names for a dedicated NationBuilder Info.plist file, which is the suggested
// method for storing relevant configuration. Refer to the implementation file
// for actual values for these keys when creating your Info.plist file.
extern NSString * __nonnull const NBInfoFileName;
extern NSString * __nonnull const NBInfoBaseURLFormatKey;
extern NSString * __nonnull const NBInfoClientIdentifierKey;
extern NSString * __nonnull const NBInfoNationSlugKey;
extern NSString * __nonnull const NBInfoRedirectPathKey;
extern NSString * __nonnull const NBInfoTestTokenKey;

// Storing the client secret is discouraged for apps not built by NationBuilder.
extern NSString * __nonnull const NBInfoClientSecretKey;

// To use our icon font you must add 'pe-icon-7-stroke' to 'Fonts provided by
// application' in your Info.plist.
extern NSString * __nonnull const NBIconFontFamilyName;

// Completion handlers are always called.
typedef void (^NBGenericCompletionHandler)(NSError * __nullable error);

#pragma mark - Logging

// Class(file)-based log levels give you more control over what library log messages
// show up.
typedef NS_ENUM(NSUInteger, NBLogLevel) {
    NBLogLevelNone,
    NBLogLevelError,
    NBLogLevelWarning,
    NBLogLevelInfo,
    NBLogLevelDebug,
};
// But they only work for classes that implement this protocol and allow you to
// change the log level. The common implementation uses a static var inside the
// implementation file to persist the log level for all class instances.
@protocol NBLogging <NSObject>

+ (void)updateLoggingToLevel:(NBLogLevel)logLevel;

@end
// This library uses the NBLog preprocessor macro for improved logging during development.
#if DEBUG
#   define NBLog(fmt, ...) NSLog((@"%s [%@:%d]\n> " fmt @"\n\n"), __PRETTY_FUNCTION__, @(__FILE__).lastPathComponent, __LINE__, ##__VA_ARGS__)
#else
#   define NBLog(fmt, ...) NSLog(fmt, ##__VA_ARGS__)
#endif
// NBLog is used in the form of these log-level-driven logging convenience macros.
#define NBLogError(fmt, ...)    if (LogLevel >= NBLogLevelError)    NBLog(@"ERROR: " fmt, ##__VA_ARGS__)
#define NBLogWarning(fmt, ...)  if (LogLevel >= NBLogLevelWarning)  NBLog(@"WARNING: " fmt, ##__VA_ARGS__)
#define NBLogInfo(fmt, ...)     if (LogLevel >= NBLogLevelInfo)     NBLog(@"INFO: " fmt, ##__VA_ARGS__)
#define NBLogDebug(fmt, ...)    if (LogLevel >= NBLogLevelDebug)    NBLog(@"DEBUG: " fmt, ##__VA_ARGS__)

#pragma mark - Protocols

@protocol NBDictionarySerializing <NSObject>

- (nonnull instancetype)initWithDictionary:(nonnull NSDictionary *)dictionary;
- (nonnull NSDictionary *)dictionary;
- (BOOL)isEqualToDictionary:(nonnull NSDictionary *)dictionary;

@end


text:
  (function(global) {
    'use strict';

    var TestHelpers = global.TestHelpers = global.TestHelpers || {};

    TestHelpers.flushAsynchronousOperations = flushAsynchronousOperations;
    TestHelpers.forceXIfStamp = forceXIfStamp;
    TestHelpers.fireEvent = fireEvent;
  })(this);


text:
#include <pdal/pdal_test_main.hpp>

#include <pdal/util/FileUtils.hpp>
#include <pdal/util/Utils.hpp>

#include "Support.hpp"

using namespace pdal;

TEST(FileUtilsTest, test_file_ops)
{
    std::string tmp1(Support::temppath("unittest1.tmp"));
    std::string tmp2(Support::temppath("unittest2.tmp"));

    // first, clean up from any previous test run
    FileUtils::deleteFile(tmp1);
    FileUtils::deleteFile(tmp2);
    EXPECT_TRUE(FileUtils::fileExists(tmp1)==false);
    EXPECT_TRUE(FileUtils::fileExists(tmp2)==false);

    // write test
    std::ostream* ostr = FileUtils::createFile(tmp1);
    *ostr << "yow";
    FileUtils::closeFile(ostr);

    EXPECT_EQ(FileUtils::fileExists(tmp1), true);
    EXPECT_EQ(FileUtils::fileSize(tmp1), 3U);

    // rename test
    FileUtils::renameFile(tmp2,tmp1);
    EXPECT_TRUE(FileUtils::fileExists(tmp1)==false);
    EXPECT_TRUE(FileUtils::fileExists(tmp2)==true);

    // read test
    std::istream* istr = FileUtils::openFile(tmp2);
    std::string yow;
    *istr >> yow;
    FileUtils::closeFile(istr);
    EXPECT_TRUE(yow=="yow");

    // delete test
    FileUtils::deleteFile(tmp2);
    EXPECT_TRUE(FileUtils::fileExists(tmp2)==false);
}

TEST(FileUtilsTest, test_readFileIntoString)
{
    const std::string filename = Support::datapath("text/text.txt");
    EXPECT_TRUE(FileUtils::fileExists(filename));

    std::string source = FileUtils::readFileIntoString(filename);

    std::string ref = "This is a file that allows us to test that we "
        "can read a text file into a string through the file utils.\n";

    EXPECT_TRUE(source == ref);
}

TEST(FileUtilsTest, test_getcwd)
{
#if 0
    // this is hardcoded for mpg's environment
    const std::string cwd = FileUtils::getcwd();
    EXPECT_TRUE(cwd == "D:/dev/pdal/test/unit/");
#endif
}

#ifdef _WIN32
static const std::string drive = "A:";
#else
static const std::string drive = "";
#endif

static std::string normalize(const std::string p)
{
    return Utils::replaceAll(p, "\\", "/");
}

static void compare_paths(const std::string a, const std::string b)
{
    EXPECT_EQ(normalize(a), normalize(b));
}

TEST(FileUtilsTest, test_toAbsolutePath)
{
    using namespace std;

    const string root = FileUtils::getcwd();

    // check 1-arg version: make absolute when file is relative, via current working dir
    const string a = FileUtils::toAbsolutePath("foo.txt");
    compare_paths(a, root + "foo.txt");

    // check 1-arg version: make absolute when file is already absolute
    const string b = FileUtils::toAbsolutePath(drive + "/baz/foo.txt");
    compare_paths(b, drive + "/baz/foo.txt");

    // check 2-arg version: make absolute when file relative, via given base
    const string c = FileUtils::toAbsolutePath("foo.txt", drive + "/a/b/c/d");
    compare_paths(c, drive + "/a/b/c/d/foo.txt");

    // check 2-arg version: make absolute when file is relative, via given base (which isn't absolute)
    const string d = FileUtils::toAbsolutePath("foo.txt", "x/y/z");
    compare_paths(d, root + "x/y/z/" + "foo.txt");

    // check 1-arg version: make absolute when file is already absolute
    const string e = FileUtils::toAbsolutePath(drive+"/baz/foo.txt", drive+"/a/b/c/d");
    compare_paths(e, drive + "/baz/foo.txt");
}

TEST(FileUtilsTest, test_getDirectory)
{
    // test absolute case
    const std::string a = FileUtils::getDirectory(drive + "/a/b/foo.txt");
    compare_paths(a, drive + "/a/b/");

    // test relative case
    const std::string b = FileUtils::getDirectory("a/b/foo.txt");
    compare_paths(b, "a/b/");
}

TEST(FileUtilsTest, test_isAbsolute)
{
    // test absolute case
    const bool a = FileUtils::isAbsolutePath(drive + "/a/b/foo.txt");
    EXPECT_TRUE(a);

    // test relative case
    const bool b = FileUtils::isAbsolutePath("a/b/foo.txt");
    EXPECT_TRUE(!b);
}

TEST(FileUtilsTest, filename)
{
    std::string filename = "/foo//bar//baz.c";
    EXPECT_EQ(FileUtils::getFilename(filename), "baz.c");
}


text:
use strict;
package main;
require("lib_inputCheck.pl");

# Set UserIndex
$userIndex = setUserIndex();

# init message variables
$sessionObj->param("userMessage", "");
my $errorMessage = "";

# Login is admin
if ($sessionObj->param("role") eq "admin") {
	$adminName = $sessionObj->param("selectedAdmin");
	$templateName = trim($request->param('templateName'));
	securityCheckTemplateName($adminName, $templateName);
	my $osName = trim($request->param('osName'));
	my $serviceName = trim($request->param('serviceName'));
	deleteTemplateService($adminName, $templateName, $osName, $serviceName);
	$queryString = "templateName=" . URLEncode($templateName) .
								"&osName=" . URLEncode($osName) .
								"&serviceName=" . URLEncode($serviceName);

} else {
	# Login is user
	die('ERROR: invalid value for $sessionObj->param("role")')
}

################################################### SUBROUTINES
#deleteTemplateService
sub deleteTemplateService {
	my ($adminName, $templateName, $osName, $serviceName) = @_;

	my $metricTemplate = lock_retrieve("$perfhome/var/db/users/$adminName/metricTemplates/$templateName.ser") or die("Could not lock_retrieve from $perfhome/var/db/users/$adminName/metricTemplates/$templateName.ser\n");
	$ruleSetIndex = $metricTemplate->getRuleSetIndex();
	delete($ruleSetIndex->{$osName}->{$serviceName});
	$metricTemplate->lock_store("$perfhome/var/db/users/$adminName/metricTemplates/$templateName.ser") or die "ERROR: Can't store $perfhome/var/db/users/$adminName/metricTemplates/$templateName.ser\n";
}

1;


text:
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package entities;

import java.io.Serializable;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 * @author ady
 */
@Entity
@XmlRootElement
public class Seller implements Serializable {

    private static final long serialVersionUID = 6L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private Double rating;
    private String name;
    private int phoneNumber;
    private String email;
    private String adress;
    private String zip;

    @OneToMany
    private List<Auction> auctions;

    public Seller(){

    }

    public Seller(Long id, Double rating, String name, int phoneNumber, String email, String adress, String zip, List<Auction> auctions) {
        this.id = id;
        this.rating = rating;
        this.name = name;
        this.phoneNumber = phoneNumber;
        this.email = email;
        this.adress = adress;
        this.zip = zip;
        this.auctions = auctions;
    }

    public List<Auction> getAuctions() {
        return auctions;
    }

    public void setAuctions(List<Auction> auctions) {
        this.auctions = auctions;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(int phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getAdress() {
        return adress;
    }

    public void setAdress(String adress) {
        this.adress = adress;
    }

    public String getZip() {
        return zip;
    }

    public void setZip(String zip) {
        this.zip = zip;
    }

    public Double getRating() {
        return rating;
    }

    public void setRating(Double rating) {
        this.rating = rating;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Seller)) {
            return false;
        }
        Seller other = (Seller) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "entities.Seller[ id=" + id + " ]";
    }

}


text:
id: a2f1d72d9b908d0bd72bb9f6
title: Make a Person
challengeType: 5
videoUrl: ''
localeTitle: Faça uma pessoa
---

## Description

 Preencha o construtor de objeto com os seguintes métodos abaixo:
 getFirstName () getLastName () getFullName () setFirstName (primeiro) setLastName (last) setFullName (firstAndLast)
 Execute os testes para ver a saída esperada para cada método. Os métodos que aceitam um argumento devem aceitar apenas um argumento e ele deve ser uma string. Esses métodos devem ser os únicos meios disponíveis de interação com o objeto. Lembre-se de usar Read-Search-Ask se você ficar preso. Tente emparelhar o programa. Escreva seu próprio código.

## Instructions

## Tests

```yml
tests:
  - text: <code>Object.keys(bob).length</code> deve retornar 6.
    testString: 'assert.deepEqual(Object.keys(bob).length, 6, "<code>Object.keys(bob).length</code> should return 6.");'
  - text: <code>bob instanceof Person</code> deve retornar true.
    testString: 'assert.deepEqual(bob instanceof Person, true, "<code>bob instanceof Person</code> should return true.");'
  - text: <code>bob.firstName</code> deve retornar indefinido.
    testString: 'assert.deepEqual(bob.firstName, undefined, "<code>bob.firstName</code> should return undefined.");'
  - text: <code>bob.lastName</code> deve retornar indefinido.
    testString: 'assert.deepEqual(bob.lastName, undefined, "<code>bob.lastName</code> should return undefined.");'
  - text: <code>bob.getFirstName()</code> deve retornar "Bob".
    testString: 'assert.deepEqual(bob.getFirstName(), "Bob", "<code>bob.getFirstName()</code> should return "Bob".");'
  - text: <code>bob.getLastName()</code> deve retornar "Ross".
    testString: 'assert.deepEqual(bob.getLastName(), "Ross", "<code>bob.getLastName()</code> should return "Ross".");'
  - text: <code>bob.getFullName()</code> deve retornar "Bob Ross".
    testString: 'assert.deepEqual(bob.getFullName(), "Bob Ross", "<code>bob.getFullName()</code> should return "Bob Ross".");'
  - text: <code>bob.getFullName()</code> deve retornar "Haskell Ross" depois de <code>bob.setFirstName("Haskell")</code> .
    testString: 'assert.strictEqual((function () { bob.setFirstName("Haskell"); return bob.getFullName(); })(), "Haskell Ross", "<code>bob.getFullName()</code> should return "Haskell Ross" after <code>bob.setFirstName("Haskell")</code>.");'
  - text: <code>bob.getFullName()</code> deve retornar "Haskell Curry" depois de <code>bob.setLastName("Curry")</code> .
    testString: 'assert.strictEqual((function () { var _bob=new Person("Haskell Ross"); _bob.setLastName("Curry"); return _bob.getFullName(); })(), "Haskell Curry", "<code>bob.getFullName()</code> should return "Haskell Curry" after <code>bob.setLastName("Curry")</code>.");'
  - text: <code>bob.getFullName()</code> deve retornar "Haskell Curry" depois de <code>bob.setFullName("Haskell Curry")</code> .
    testString: 'assert.strictEqual((function () { bob.setFullName("Haskell Curry"); return bob.getFullName(); })(), "Haskell Curry", "<code>bob.getFullName()</code> should return "Haskell Curry" after <code>bob.setFullName("Haskell Curry")</code>.");'
  - text: <code>bob.getFirstName()</code> deve retornar "Haskell" depois de <code>bob.setFullName("Haskell Curry")</code> .
    testString: 'assert.strictEqual((function () { bob.setFullName("Haskell Curry"); return bob.getFirstName(); })(), "Haskell", "<code>bob.getFirstName()</code> should return "Haskell" after <code>bob.setFullName("Haskell Curry")</code>.");'
  - text: <code>bob.getLastName()</code> deve retornar "Curry" depois de <code>bob.setFullName("Haskell Curry")</code> .
    testString: 'assert.strictEqual((function () { bob.setFullName("Haskell Curry"); return bob.getLastName(); })(), "Curry", "<code>bob.getLastName()</code> should return "Curry" after <code>bob.setFullName("Haskell Curry")</code>.");'

```

## Challenge Seed

```js
var Person = function(firstAndLast) {
  // Complete the method below and implement the others similarly
  this.getFullName = function() {
    return "";
  };
  return firstAndLast;
};

var bob = new Person('Bob Ross');
bob.getFullName();

```

## Solution

```js
// solution required
```


text:
require 'test_helper'

class BorderTest < Minitest::Test
  include WhiteListInterface

  def clazz
    MtgApi::Utilities::Border
  end
end


text:
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import {hashHistory} from "react-router";
import { viewNode } from '../../actions/actions';
import Split from 'grommet/components/Split';
import Article from 'grommet/components/Article';
import Markdown from 'grommet/components/Markdown';
import Header from 'grommet/components/Header';
import Heading from 'grommet/components/Heading';
import Section from 'grommet/components/Section';
import Box from 'grommet/components/Box';
import Anchor from 'grommet/components/Anchor';
import Button from 'grommet/components/Button';
import Notification from 'grommet/components/Notification';
import List from 'grommet/components/List';
import ListItem from 'grommet/components/ListItem';
import LinkPreviousIcon from 'grommet/components/icons/base/LinkPrevious';
import MoreIcon from 'grommet/components/icons/base/More';

import NoteActions from './NoteActions';

class NoteShow extends Component {

	constructor(props) {
		super(props);
		this._onResponsive = this._onResponsive.bind(this);
		this._onToggleSidebar = this._onToggleSidebar.bind(this);

		this.state = {
			layerName: undefined,
			showSidebarWhenSingle: false
		};
	}

	componentDidMount() {
		var nodeId = this.props.params.nodeId;
		// load init sketch
		this.props.dispatch(viewNode(nodeId));

		document.title = this.props.note.name;
		// this.props.dispatch(loadItem(this.props.uri));
	}

	componentWillReceiveProps(nextProps) {
		if (nextProps.note) {
			document.title = nextProps.note.name;
		}
	}

	componentWillUnmount() {
		document.title = 'orgdown';
		// have to unload snapshots first!
		// this.props.dispatch(unloadVmSnapshots());
		// this.props.dispatch(unloadItem());
	}

	_onResponsive(responsive) {
		// this.props.dispatch(vmResponsive(responsive));
	}

	_onToggleSidebar() {
		this.setState({
			showSidebarWhenSingle: !this.state.showSidebarWhenSingle
		});
	}

	render() {
		const { note } = this.props;

		let sidebar;
		let onSidebarClose = this._onToggleSidebar;

		sidebar = (
			<NoteActions note={note} onClose={onSidebarClose} />
		);

		return (
			<Split flex="left" separator={true}
				priority={this.state.showSidebarWhenSingle ? 'right' : 'left'}
				onResponsive={this._onResponsive}>

						<Box direction="row" align="center" pad={{ between: 'small' }}
							responsive={false}>
							<Anchor icon={<LinkPreviousIcon />} onClick={hashHistory.goBack}
								a11yTitle="Return" />
							<Heading tag="h1" margin="none">
								{note.name}
							</Heading>
						</Box>

						<Markdown content={note.content} />

				{sidebar}
			</Split>
		);
	}
}

NoteShow.propTypes = {
	category: PropTypes.string.isRequired, /// remove?
	nav: PropTypes.object.isRequired,
	notifications: PropTypes.object,
	responsive: PropTypes.oneOf(['single', 'multiple']),
	role: PropTypes.string,
	uri: PropTypes.string.isRequired,
	virtualMachine: PropTypes.object
};

let select = (state, props) => {
	return {
		note: state.note,
	};
};

export default connect(select)(NoteShow);


text:
namespace RosettaStone::Generic
{
//! Draws a card in the deck.
//! \param player The player to add card to the hand.
//! \param cardToDraw A card to draw in the deck.
//! \return A dynamic allocated entity object.
Entity* Draw(Player& player, Entity* cardToDraw = nullptr);

//! Draws a specific card to the hand.
//! \param player The player to add card to the hand.
//! \param card A card to draw to the hand.
//! \return A dynamic allocated entity object.
Entity* DrawCard(Player& player, Card&& card);
}  // namespace RosettaStone::Generic

#endif  // ROSETTASTONE_DRAW_HPP


text:
js.jqgrid
*********

Introduction
============

This library packages `jqgrid`_ for `fanstatic`_.

.. _`fanstatic`: http://fanstatic.org
.. _`jqgrid`: http://www.trirand.com/jqgridwiki/

To include the grid, call

    js.jqgrid.jqgrid.need()

then you also need to add
a language, for example

    js.jqgrid.jqgrid_i18n_en.need()

This requires integration between your web framework and ``fanstatic``,
and making sure that the original resources (shipped in the ``resources``
directory in ``js.jqgrid``) are published to some URL.

The provided jqgrid code is licenced under MIT and GPL, the integration code
uses a BSD Licence.


text:
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Code generated by Microsoft (R) AutoRest Code Generator.

package com.azure.resourcemanager.machinelearning.models;

import com.azure.core.annotation.Fluent;
import com.azure.core.util.logging.ClientLogger;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import java.util.List;

/** The CustomTargetLags model. */
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "mode")
@JsonTypeName("Custom")
@Fluent
public final class CustomTargetLags extends TargetLags {
    /*
     * [Required] Set target lags values.
     */
    @JsonProperty(value = "values", required = true)
    private List<Integer> values;

    /** Creates an instance of CustomTargetLags class. */
    public CustomTargetLags() {
    }

    /**
     * Get the values property: [Required] Set target lags values.
     *
     * @return the values value.
     */
    public List<Integer> values() {
        return this.values;
    }

    /**
     * Set the values property: [Required] Set target lags values.
     *
     * @param values the values value to set.
     * @return the CustomTargetLags object itself.
     */
    public CustomTargetLags withValues(List<Integer> values) {
        this.values = values;
        return this;
    }

    /**
     * Validates the instance.
     *
     * @throws IllegalArgumentException thrown if the instance is not valid.
     */
    @Override
    public void validate() {
        super.validate();
        if (values() == null) {
            throw LOGGER
                .logExceptionAsError(
                    new IllegalArgumentException("Missing required property values in model CustomTargetLags"));
        }
    }

    private static final ClientLogger LOGGER = new ClientLogger(CustomTargetLags.class);
}


text: .. automodule:: screenflow.style


text:
package org.daige.common;

import org.daige.domain.ValidationParameter;

/**
 * @Author frank
 * @Date 17-5-25
 */
// 缺省可按服务接口区分验证场景,如:@NotNull(groups = ValidationService.class)
public interface IValidationService {

    // 与方法同名接口,首字母大写,用于区分验证场景,
    // 如:@NotNull(groups = ValidationService.Save.class),可选
    @interface Save{}
    void save(ValidationParameter parameter);

    void update(ValidationParameter parameter);

}


text:
require 'flattr/error/server_error'

module Flattr
  # Raised when Flattr returns the HTTP status code 500
  class Error::InternalServerError < Flattr::Error::ServerError
  end
end


text:
Traditional version using **[Flask](http://flask.pocoo.org/)** as web server:

```
$ python2.7 flask_skeleton.py <token> <listening_port> https://<domain>/abc
$ python3.5 flask_counter.py <token> <listening_port> https://<domain>/abc
```

Async version using **[aiohttp](http://aiohttp.readthedocs.org/en/stable/)** as web server:

```
$ python3.5 aiohttp_skeletona.py <token> <listening_port> https://<domain>/abc
$ python3.5 aiohttp_countera.py <token> <listening_port> https://<domain>/abc
```

Remember you will have to set up the **webhook URL, SSL certificate, and web server** on your own.

## Telepot's Webhook Interface

Setting up a **[webhook](https://core.telegram.org/bots/api#setwebhook)** is
more complicated than using `getUpdates()` because:

1. You have to obtain an URL
2. You have to obtain and set up an SSL certificate for the URL
3. You have to set up a web server to handle the POST requests coming from Telegram servers

Webhook also presents a subtle problem: closely bunched updates may arrive out of order.
That is, update_id `1000` may arrive ahead of update_id `999`, if the two are issued by
Telegram servers very closely. Unless a bot absolutely doesn't care about update order,
it will have to re-order them in some way.

Telepot has a mechanism to interface with web applications, and it takes care of re-ordering
for you. The mechanism is simple: you call `message_loop()` as usual, but supply an additional
parameter `source`, which is a queue.

```python
# for Python 2 and 3
try:
    from Queue import Queue
except ImportError:
    from queue import Queue

def handle(msg):
    # ......

bot = telepot.Bot(TOKEN)
update_queue = Queue()

# get updates from queue, not from Telegram servers
bot.message_loop(handle, source=update_queue)
```

The web application, upon receiving a POST request, dumps data into the queue
for the bot to retrieve at the other end. The bot will re-order the updates if necessary.
Using [Flask](http://flask.pocoo.org/) as the web application framework:

```python
from flask import Flask, request

app = Flask(__name__)

@app.route('/webhook_path', methods=['GET', 'POST'])
def pass_update():
    update_queue.put(request.data)  # dump data to queue
    return 'OK'
```


text:
/* debugging styles */
#debug p {padding:0;margin:0.2em 0.2em 0;clear:both; float:left; text-align:left; font:normal 0.9em 'Lucida Console', 'Courier New', monospaced; color:#888; }
#debug .warning {padding:0;background:none;color:#f93;border:none;}
#debug .error	{padding:0;background:none;color:#f62b2a;border:none;}
#debug .info	{padding:0;background:none;color:#5babeb;border:none;}
#sub #debug , #local #debug {float:left;background:#454545;}


text:
package com.nbtaskfocus.core.ui.nodes;

import com.nbtaskfocus.model.api.Task;
import com.nbtaskfocus.model.api.TaskList;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
import org.openide.util.WeakListeners;

/**
 *
 * @author Tushar Joshi <tusharvjoshi@gmail.com>
 */
public class TaskChildren extends ChildFactory<Task> implements PropertyChangeListener {

    private TaskList taskList = null;
    private Map<Task,TaskNode> nodeMap = new HashMap<Task,TaskNode>();

    public TaskChildren() {
        taskList = TaskList.getDefault();
        taskList.addPropertyChangeListener(
                WeakListeners.propertyChange(this, taskList));
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        String propertyName = evt.getPropertyName();
        if (TaskList.EVENTNAME_TASKADDED.equals(propertyName)
                || TaskList.EVENTNAME_TASKDELETED.equals(propertyName)) {
            refresh();
        }
    }

    @Override
    protected boolean createKeys(List<Task> list) {
        int count = taskList.getCount();

        for( int i = 0 ; i < count; i++) {
            list.add( TaskList.getDefault().getTask(i));
        }
        nodeMap.clear();
        return true;
    }

    @Override
    protected Node createNodeForKey(Task key) {
        Node node = new TaskNode(key);
        nodeMap.put(key, (TaskNode)node);
        return node;
    }

    public void refresh() {
        this.refresh(true);
    }

}


text:
'use strict';

var t = require('tcomb-react');
var Factory = require('react-bootstrap/OverlayTrigger');
var name = t.react.getDisplayName(Factory);

var PositiveInt = require('./util/PositiveInt');
var Placement = require('./util/Placement');
var TriggerA = t.enums.of('manual click hover focus', 'TriggerA'); // TODO understand what exactly are these types in react-bootstrap
var TriggerB = t.enums.of('click hover focus', 'TriggerB');
var TriggerC = t.list(TriggerB, 'TriggerC');
var Trigger = t.union([TriggerA, TriggerC], 'Trigger');

var Type = t.struct({
  __tag__:              t.enums.of(name, name),
  container:            t.maybe(t.react.Mountable),
  trigger:              t.maybe(Trigger),
  placement:            t.maybe(Placement),
  delay:                t.maybe(PositiveInt),
  delayShow:            t.maybe(PositiveInt),
  delayHide:            t.maybe(PositiveInt),
  defaultOverlayShown:  t.maybe(t.Bool),
  overlay:              t.react.Renderable,
  children:             t.Any
}, name);

module.exports = t.react.bind(Factory, Type, {strict: false});


text:
package com.simple.app.async.todo.service;

import com.github.pgasync.Db;
import com.github.pgasync.Row;
import com.simple.app.async.todo.domain.Todo;
import rx.Observable;

import java.sql.Timestamp;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

import static java.util.Arrays.asList;

public class TodoService {

    private static final Function<Row, Todo> ROW_MAPPER = row -> new Todo(
            row.getLong("id"),
            row.getString("owner"),
            row.getString("title"),
            row.getString("description"),
            row.getTimestamp("created_on").toLocalDateTime()
    );

    private static final Function<Todo, List<Object>> ROW_UNMAPPER = todo -> asList(
            todo.getOwner(),
            todo.getTitle(),
            todo.getDescription(),
            Timestamp.valueOf(todo.getCreatedOn()),
            todo.getId()
    );

    private final Db db;

    public TodoService(Db db) {
        this.db = db;
    }

    public Observable<Todo> findAll() {
        return db.queryRows("SELECT * FROM todo LIMIT 10").map(ROW_MAPPER::apply);
    }

    public Observable<Todo> findOne(Long id) {
        return db.queryRows("SELECT * FROM todo where id = $1", id).map(ROW_MAPPER::apply);
    }

    public Observable<Todo> save(Todo todo) {
        Object[] params = ROW_UNMAPPER.apply(todo).toArray();

        final String sql = todo.getId() == null
                ? "INSERT INTO todo (owner, title, description, created_on) VALUES ($1, $2, $3, $4) RETURNING *"
                : "UPDATE todo SET (owner, title, description, created_on) = ($1,$2,$3,$4) WHERE id = $5 RETURNING *";
        params = todo.getId() == null ? Arrays.copyOfRange(params, 0, 4) : params;
        return db.queryRows(sql, params).map(ROW_MAPPER::apply);
    }

    public Observable<Boolean> remove(Long id) {
        return db.querySet("DELETE FROM todo WHERE id = $1", id).map(set -> set.updatedRows() > 0);
    }

}