Example usage for java.util.concurrent.atomic AtomicReference get

List of usage examples for java.util.concurrent.atomic AtomicReference get

Introduction

In this page you can find the example usage for java.util.concurrent.atomic AtomicReference get.

Prototype

public final V get() 

Source Link

Document

Returns the current value, with memory effects as specified by VarHandle#getVolatile .

Usage

From source file:com.microsoft.tfs.core.clients.versioncontrol.soapextensions.Workspace.java

/**
 * Undoes pending changes for matching items in this workspace. Items in
 * working folders are immediately updated. If <code>updateDisk</code> is
 * <code>false</code>, then the files on disk will not be updated in
 * response to the server commands to do so. Passing <code>false</code> for
 * <code>updateDisk</code> is not common and should only be needed in rare
 * situations.//w ww  .  j av  a2  s .  c o m
 * <p>
 * <!-- Event Origination Info -->
 * <p>
 * This method is an <b>core event origination point</b>. The
 * {@link EventSource} object that accompanies each event fired by this
 * method describes the execution context (current thread, etc.) when and
 * where this method was invoked.
 *
 * @param items
 *        the items to undo (must not be <code>null</code>)
 * @param getOptions
 *        the {@link GetOptions} to use (must not be <code>null</code>)
 * @param deleteAdds
 *        determines if adds should be deleted
 * @param itemPropertyFilters
 *        a list of versioned item properties to return with each get
 *        operation (may be <code>null</code>)
 * @return the number of items successfully undone.
 */
public int undo(final ItemSpec[] items, final GetOptions getOptions, final boolean deleteAdds,
        String[] itemPropertyFilters) {
    Check.notNull(items, "items"); //$NON-NLS-1$

    // Using web service directly so merge filters configured on client
    itemPropertyFilters = client.mergeWithDefaultItemPropertyFilters(itemPropertyFilters);

    client.getEventEngine()
            .fireOperationStarted(new UndoOperationStartedEvent(EventSource.newFromHere(), this, items));

    int ret = 0;
    try {
        if (items.length == 0) {
            return 0;
        }

        final AtomicReference<Failure[]> failuresHolder = new AtomicReference<Failure[]>();
        final AtomicBoolean onlineOperationHolder = new AtomicBoolean();
        final AtomicReference<ChangePendedFlags> changePendedFlagsHolder = new AtomicReference<ChangePendedFlags>();

        final GetOperation[] operations = client.getWebServiceLayer().undoPendingChanges(getName(),
                getOwnerName(), items, failuresHolder, null, itemPropertyFilters, onlineOperationHolder, false,
                changePendedFlagsHolder);

        if (operations != null && operations.length > 0) {
            if (isLocal()) {
                final GetEngine getEngine = new GetEngine(client);
                getEngine.processGetOperations(this, ProcessType.UNDO, RequestType.NONE,
                        new GetOperation[][] { operations }, getOptions, deleteAdds,
                        onlineOperationHolder.get(), changePendedFlagsHolder.get());

                ret = operations.length;
            } else {
                final String messageFormat = Messages
                        .getString("Workspace.OperationCompletedForRemoteWorkspaceButGetRequiredFormat"); //$NON-NLS-1$
                final String message = MessageFormat.format(messageFormat, getDisplayName());

                client.getEventEngine().fireNonFatalError(
                        new NonFatalErrorEvent(EventSource.newFromHere(), this, new Exception(message)));
            }
        }

        if (changePendedFlagsHolder.get().contains(ChangePendedFlags.WORKING_FOLDER_MAPPINGS_UPDATED)) {
            invalidateMappings();
        }

        client.reportFailures(this, failuresHolder.get());
    } finally {
        client.getEventEngine().fireOperationCompleted(
                new UndoOperationCompletedEvent(EventSource.newFromHere(), this, items));

        Workstation.getCurrent(getClient().getConnection().getPersistenceStoreProvider())
                .notifyForWorkspace(this, Notification.VERSION_CONTROL_PENDING_CHANGES_CHANGED);
    }

    return ret;
}

From source file:com.microsoft.tfs.core.clients.versioncontrol.soapextensions.Workspace.java

/**
 * Unshelves changes, restoring them to the workspace.
 *
 * @param shelvesetName/*w w  w. ja v a  2 s  .c om*/
 *        the name of the shelveset to restore (must not be
 *        <code>null</code> or empty).
 * @param shelvesetOwner
 *        the owner of the shelveset to restore (must not be
 *        <code>null</code> or empty).
 * @param itemSpecs
 *        the items to restore. If this array is null, all changes in the
 *        named shelveset are restored. If this array is empty, no changes
 *        will be unshelved.
 * @param itemPropertyFilters
 *        a list of versioned item properties to return with each get
 *        operation (may be <code>null</code>)
 * @param shelvesetPropertyFilters
 *        the list of properties to be returned on the shelvesets. To get
 *        all properties pass a single filter that is simply "*" (may be
 *        <code>null</code>)
 * @param merge
 *        <code>true</code> to allow merging conflicting changes in the
 *        shelveset with local pending changes ({@link Conflict}s will be
 *        produced)
 * @param noAutoResolve
 *        <code>true</code> to disable automerging of conflicting changes,
 *        <code>false</code> to perform an automerge
 * @return the {@link UnshelveResult} which contains the {@link Shelveset}
 *         unshelved and the {@link GetStatus} for the get operations which
 *         were processed, or <code>null</code> if the unshelve operation
 *         failed with no further status from the server
 */
public UnshelveResult unshelve(final String shelvesetName, final String shelvesetOwner,
        final ItemSpec[] itemSpecs, String[] itemPropertyFilters, final String[] shelvesetPropertyFilters,
        final boolean merge, final boolean noAutoResolve) throws UnshelveException {
    Check.notNullOrEmpty(shelvesetName, "shelvesetName"); //$NON-NLS-1$
    Check.notNullOrEmpty(shelvesetOwner, "shelvesetOwner"); //$NON-NLS-1$

    log.debug("Unshelve started."); //$NON-NLS-1$

    final AtomicReference<Failure[]> failuresHolder = new AtomicReference<Failure[]>();
    final AtomicReference<GetOperation[]> getOperationsHolder = new AtomicReference<GetOperation[]>();
    final AtomicReference<Conflict[]> conflictsHolder = new AtomicReference<Conflict[]>();
    final AtomicReference<ChangePendedFlags> changePendedFlagsHolder = new AtomicReference<ChangePendedFlags>();

    // Using web service directly so merge filters configured on client
    itemPropertyFilters = client.mergeWithDefaultItemPropertyFilters(itemPropertyFilters);

    final Shelveset shelveset = client.getWebServiceLayer().unshelve(shelvesetName, shelvesetOwner, getName(),
            getOwnerName(), itemSpecs, null, itemPropertyFilters, shelvesetPropertyFilters, merge,
            failuresHolder, getOperationsHolder, conflictsHolder, changePendedFlagsHolder);

    log.debug("Preparing get operations."); //$NON-NLS-1$

    /*
     * Print out any failures and bail if there were any serious errors.
     */
    if (failuresHolder.get().length > 0) {
        client.reportFailures(this, failuresHolder.get());

        if (getOperationsHolder.get().length == 0) {
            throw new UnshelveException(Messages.getString("Workspace.NoChangesUnshelved")); //$NON-NLS-1$
        }
    }

    /*
     * Turns out that the result.value can be null if the unshelve fails. In
     * which case return null and let the caller display the error message
     * that will have been thrown from the above events.
     */
    if (shelveset == null) {
        return null;
    }

    final GetOperation[] getOperations = getOperationsHolder.get();
    Conflict[] conflicts = conflictsHolder.get();

    /*
     * Convert the get operations into pending changes so we can pass them
     * through the event.
     */
    final PendingChange[] unshelvedChanges = getOperations != null ? new PendingChange[getOperations.length]
            : new PendingChange[0];

    if (getOperations != null && getOperations.length > 0) {
        for (int i = 0; i < getOperations.length; i++) {
            getOperations[i].setProcessType(ProcessType.UNSHELVE);
            unshelvedChanges[i] = new PendingChange(this, getOperations[i], ProcessType.UNSHELVE);
        }
    }

    client.getEventEngine().fireOperationStarted(
            new UnshelveShelvesetStartedEvent(EventSource.newFromHere(), this, shelveset, unshelvedChanges));

    GetStatus getStatus = new GetStatus();

    try {
        if (getOperations != null && getOperations.length > 0) {
            final GetEngine getEngine = new GetEngine(client);

            getStatus = getEngine.processGetOperations(this, ProcessType.UNSHELVE, getOperations,
                    GetOptions.NONE, changePendedFlagsHolder.get());
        }

        /* We want to auto resolve conflicts if the option is set */
        int resolvedConflicts = 0;
        if (conflicts != null && !noAutoResolve) {
            /* Actually auto resolve the conflicts */
            final Conflict[] remainingConflicts = client.autoResolveValidConflicts(this, conflicts,
                    AutoResolveOptions.ALL_SILENT);

            resolvedConflicts = conflicts.length - remainingConflicts.length;
            conflicts = remainingConflicts;
        }

        /* Fire events for conflicts found during the unshelve. */
        int nonResolvedConflicts = 0;
        if (conflicts != null) {
            for (final Conflict conflict : conflicts) {
                if (conflict.getResolution() == Resolution.NONE) {
                    nonResolvedConflicts++;

                    client.getEventEngine().fireConflict(new ConflictEvent(EventSource.newFromHere(),
                            conflict.getYourServerItemSource(), this,
                            ConflictDescriptionFactory.getConflictDescription(
                                    ConflictCategory.getConflictCategory(conflict), conflict).getDescription(),
                            true));
                }
            }
        }

        getStatus.setNumConflicts(getStatus.getNumConflicts() + nonResolvedConflicts);
        getStatus.setNumResolvedConflicts(resolvedConflicts);
    } finally {
        client.getEventEngine().fireOperationCompleted(new UnshelveShelvesetCompletedEvent(
                EventSource.newFromHere(), this, shelveset, unshelvedChanges));

        Workstation.getCurrent(getClient().getConnection().getPersistenceStoreProvider())
                .notifyForWorkspace(this, Notification.VERSION_CONTROL_PENDING_CHANGES_CHANGED);
    }

    if (changePendedFlagsHolder.get().contains(ChangePendedFlags.WORKING_FOLDER_MAPPINGS_UPDATED)) {
        invalidateMappings();
    }

    return new UnshelveResult(shelveset, getStatus, unshelvedChanges, conflicts);
}

From source file:com.microsoft.tfs.core.clients.versioncontrol.soapextensions.Workspace.java

/**
 * Merge changes made between two versions to items in a given source path
 * into a given target path. The result of this method is that one or more
 * merge items are pended./*from ww w  .j av  a 2 s. c om*/
 * <p>
 * <!-- Event Origination Info -->
 * <p>
 * This method is an <b>core event origination point</b>. The
 * {@link EventSource} object that accompanies each event fired by this
 * method describes the execution context (current thread, etc.) when and
 * where this method was invoked.
 *
 * @param sourceSpec
 *        the local or server path of the source of the merge; where the
 *        changes are copied from, and the recursion type to match the given
 *        source path with (must not be <code>null</code>, path must not be
 *        <code>null</code> or empty)
 * @param targetPath
 *        the local or server path of the target of the merge; where the
 *        changes will end up (must not be <code>null</code> or empty).
 * @param sourceVersionFrom
 *        the version (inclusive) of the source item to start including
 *        changes from for this merge operation. null indicates all versions
 *        beginning with version 1.
 * @param sourceVersionTo
 *        the version (inclusive) of the source item to stop including
 *        changes from for this merge operation. null indicates all versions
 *        up to and including tip version.
 * @param lockLevel
 *        the lock level to apply to the pended changes (must not be
 *        <code>null</code>)
 * @param mergeFlags
 *        any merge options to apply during this merge (must not be
 *        <code>null</code>)
 * @param itemPropertyFilters
 *        a list of versioned item properties to return with each get
 *        operation (may be <code>null</code>)
 * @return a GetStatus instance with the results of the merge operation.
 */
public GetStatus merge(final ItemSpec sourceSpec, final String targetPath, final VersionSpec sourceVersionFrom,
        final VersionSpec sourceVersionTo, final LockLevel lockLevel, final MergeFlags mergeFlags,
        String[] itemPropertyFilters) {
    Check.notNull(sourceSpec, "sourceSpec"); //$NON-NLS-1$
    Check.notNullOrEmpty(sourceSpec.getItem(), "sourceSpec.item"); //$NON-NLS-1$
    Check.notNull(sourceSpec.getRecursionType(), "sourceSpec.recursion"); //$NON-NLS-1$
    Check.notNullOrEmpty(targetPath, "targetPath"); //$NON-NLS-1$
    Check.notNull(lockLevel, "lockLevel"); //$NON-NLS-1$
    Check.notNull(mergeFlags, "mergeFlags"); //$NON-NLS-1$

    // Using web service directly so merge filters configured on client
    itemPropertyFilters = client.mergeWithDefaultItemPropertyFilters(itemPropertyFilters);

    final ItemSpec targetSpec = new ItemSpec(targetPath, RecursionType.NONE);

    int nonResolvedConflicts = 0;
    int resolvedConflicts = 0;

    client.getEventEngine()
            .fireOperationStarted(new MergeOperationStartedEvent(EventSource.newFromHere(), this));

    final AtomicReference<Failure[]> failures = new AtomicReference<Failure[]>();
    final AtomicReference<Conflict[]> conflicts = new AtomicReference<Conflict[]>();
    final AtomicReference<ChangePendedFlags> changePendedFlags = new AtomicReference<ChangePendedFlags>();

    try {
        final GetOperation[] getOps = client.getWebServiceLayer().merge(getName(), getOwnerName(), sourceSpec,
                targetSpec, sourceVersionFrom, sourceVersionTo, lockLevel, mergeFlags, failures, conflicts,
                null, itemPropertyFilters, changePendedFlags);

        final boolean discard = mergeFlags.contains(MergeFlags.ALWAYS_ACCEPT_MINE);

        // Match up these getOps and merge details (returned as Conflict
        // objects). The conflicts with matching getOps have already been
        // resolved.
        final Map<String, Conflict> pathConflictDict = new TreeMap<String, Conflict>(
                ServerPath.TOP_DOWN_COMPARATOR);
        final Map<Integer, Conflict> itemIdConflictDict = new HashMap<Integer, Conflict>();
        for (final Conflict conflict : conflicts.get()) {
            if (conflict.isResolved()) {
                // if it is a branch, and the user asked for preview, we do
                // not assign ItemIds
                // so we need to lookup by path
                if (conflict.getBaseChangeType().contains(ChangeType.BRANCH) && conflict.getYourItemID() == 0) {
                    pathConflictDict.put(conflict.getYourServerItem(), conflict);
                } else {
                    itemIdConflictDict.put(conflict.getYourItemID(), conflict);
                }
            }
        }
        for (final GetOperation getOp : getOps) {
            if (getOp.getChangeType().contains(ChangeType.BRANCH) && getOp.getItemID() == 0) {
                final Conflict conflict = pathConflictDict.get(getOp.getTargetServerItem());
                if (conflict != null) {
                    getOp.setMergeDetails(conflict);
                }
            } else {
                final Conflict conflict = itemIdConflictDict.get(getOp.getItemID());
                if (conflict != null) {
                    getOp.setMergeDetails(conflict);
                }
            }
        }

        GetStatus getStatus = null;

        if (isLocal()) {
            /*
             * We want to auto resolve conflicts if the option is set to do
             * so and we are not discarding
             */
            if (!discard && !mergeFlags.contains(MergeFlags.NO_AUTO_RESOLVE)
                    && !mergeFlags.contains(MergeFlags.NO_MERGE)) {
                if (getClient().getWebServiceLayer().getServiceLevel().getValue() < WebServiceLevel.TFS_2012_1
                        .getValue()) {
                    /*
                     * The download urls for base files were not populated
                     * on conflicts in pre 2012 servers. Let's call
                     * QueryConflicts now so that we have that information.
                     * We use sourceSpec.RecursionType here because that
                     * corresponds to what the user passed in.
                     */
                    conflicts.set(queryConflicts(new String[] { targetSpec.getItem() },
                            sourceSpec.getRecursionType() != RecursionType.NONE));
                }

                final Conflict[] remainingConflicts = getClient().autoResolveValidConflicts(this,
                        conflicts.get(), AutoResolveOptions.ALL_SILENT);

                resolvedConflicts = conflicts.get().length - remainingConflicts.length;
                conflicts.set(remainingConflicts);
            }

            // Fire events for merges that did not get resolved by the
            // server.
            // The others will get fired in get.cs as they are processed.
            for (final Conflict conflict : conflicts.get()) {
                if (conflict.getResolution() == Resolution.NONE) {
                    log.trace("Firing event on conflict: " + conflict); //$NON-NLS-1$

                    // The pending change arg is null because of the
                    // conflict.
                    client.getEventEngine()
                            .fireMerging(new MergingEvent(EventSource.newFromHere(), new Conflict(conflict),
                                    this, false, null, OperationStatus.CONFLICT, ChangeType.NONE, true,
                                    new PropertyValue[0]));

                    nonResolvedConflicts++;
                }
            }

            // When we are discarding source changes, we simply call
            // ResolveConflict.
            if (discard) {
                for (final Conflict conflict : conflicts.get()) {
                    // There is nothing to do when the resolution is
                    // AcceptYours.
                    client.getEventEngine().fireConflictResolved(new ConflictResolvedEvent(
                            EventSource.newFromHere(), this, conflict, changePendedFlags.get()));
                }

                getStatus = new GetStatus();
                getStatus.setNumOperations(conflicts.get().length);
                return getStatus;
            }

            final GetOptions options = mergeFlags.contains(MergeFlags.NO_MERGE) ? GetOptions.PREVIEW
                    : GetOptions.NONE;

            final GetEngine getEngine = new GetEngine(client);
            getStatus = getEngine.processGetOperations(this, ProcessType.MERGE, getOps, options,
                    changePendedFlags.get());

            getStatus.setNumConflicts(getStatus.getNumConflicts() + nonResolvedConflicts);
            getStatus.setNumResolvedConflicts(resolvedConflicts);
        } else if (getOps.length > 0) {
            client.getEventEngine()
                    .fireNonFatalError(new NonFatalErrorEvent(EventSource.newFromHere(), this,
                            new VersionControlException(MessageFormat.format(
                                    Messages.getString("Workspace.NoLocalChangesRemoteWorkspaceFormat"), //$NON-NLS-1$
                                    getDisplayName()))));
        }

        if (getStatus == null) {
            getStatus = new GetStatus();
            getStatus.setNumOperations(getOps.length);
        }

        if (changePendedFlags.get().contains(ChangePendedFlags.WORKING_FOLDER_MAPPINGS_UPDATED)) {
            invalidateMappings();
        }

        client.reportFailures(this, failures.get());

        for (final Failure failure : failures.get()) {
            getStatus.addFailure(failure);
        }

        return getStatus;
    } finally {
        client.getEventEngine()
                .fireOperationCompleted(new MergeOperationCompletedEvent(EventSource.newFromHere(), this));

        Workstation.getCurrent(getClient().getConnection().getPersistenceStoreProvider())
                .notifyForWorkspace(this, Notification.VERSION_CONTROL_PENDING_CHANGES_CHANGED);
    }
}

From source file:com.microsoft.tfs.core.clients.versioncontrol.soapextensions.Workspace.java

/**
 * Checkin pending changes in this workspace.
 * <p>// w  ww.  java 2 s  . co m
 * <!-- Event Origination Info -->
 * <p>
 * This method is an <b>core event origination point</b>. The
 * {@link EventSource} object that accompanies each event fired by this
 * method describes the execution context (current thread, etc.) when and
 * where this method was invoked.
 *
 * @param changes
 *        the changes to checkin (may be <code>null</code> to have the
 *        server check in all changes in this workspace)
 * @param committer
 *        if not <code>null</code>, the committer of this change. if
 *        <code>null</code>, the committer will be the authenticated user.
 * @param author
 *        if not <code>null</code>, the author of this change. if
 *        <code>null</code>, the author will be the authenticated user.
 * @param comment
 *        a text comment that will be associated with this checkin (can be
 *        <code>null</code>).
 * @param checkinNote
 *        {@link CheckinNote} object containing array of
 *        ACheckinNoteFieldValue objects. If <code>null</code>, no checkin
 *        notes are added to changeset. For a list of checkin note field
 *        names applicable to the items use the
 *        queryCheckinNoteFieldDefinitionsForServerPaths on the
 *        VersionControlClient.
 * @param associatedWorkItems
 *        work items to associate with the checkin. if <code>null</code>, no
 *        work items are associated with this checkin
 * @param policyOverrideInfo
 *        Optional information describing why checkin policies were
 *        overridden for this checkin. Pass null for a normal check-in
 *        (policies were not overridden).
 * @param flags
 *        {@link CheckinFlags} which control the checkin (must not be
 *        <code>null</code>)
 * @return the changeset number the server chooses for this changeset.
 * @throws CheckinException
 *         if conflicts caused the checkin to fail or if other errors
 *         occurred.
 * @throws ActionDeniedBySubscriberException
 *         if the check-in was denied by the server (because of a gated
 *         build definition, etc.).
 *
 * @see VersionControlClient#queryCheckinNoteFieldDefinitionsForServerPaths(String[])
 */
public int checkIn(PendingChange[] changes, final String committer, final String committerDisplayName,
        String author, String authorDisplayName, final String comment, final CheckinNote checkinNote,
        WorkItemCheckinInfo[] associatedWorkItems, final PolicyOverrideInfo policyOverrideInfo,
        final CheckinFlags flags) throws CheckinException {
    Check.isTrue(changes == null || changes.length > 0,
            "changes must be null for server-side change selection or non-empty"); //$NON-NLS-1$
    Check.notNull(flags, "flags"); //$NON-NLS-1$

    /**
     * TFS 2010 behaves strangely with gated check-ins if we send null for
     * associated work items (a non-standard subcode comes back in the
     * ActionDeniedBySubscriberException. Always send at least an empty
     * list.
     */
    if (associatedWorkItems == null) {
        associatedWorkItems = new WorkItemCheckinInfo[0];
    }

    final TaskMonitor monitor = TaskMonitorService.getTaskMonitor();

    /*
     * The total work for our progress monitor is set to 100, and subtasks
     * are allocated as percentages. For example, checkin for conflicts is
     * quick, so it takes only 2 percent. Uploading files usually takes
     * longer, so it's 80 percent. Make sure all the work done in this
     * method adds to 100.
     */
    monitor.begin("", 100); //$NON-NLS-1$

    /*
     * We sort the changes by server path so they appear in the correct
     * order when giving status information to the user.
     */
    String[] serverItems = null;
    if (changes != null) {
        changes = changes.clone();
        Arrays.sort(changes, new PendingChangeComparator(PendingChangeComparatorType.SERVER_ITEM));
        serverItems = PendingChange.toServerItems(changes);
    }

    // Lets us detect all abnormal exits (Throwable, Exception, Gated
    // checkin exception) for saved checkin reset
    boolean success = false;

    try {
        TaskMonitorService.pushTaskMonitor(monitor.newSubTaskMonitor(75));
        try {
            // Upload contents
            if (changes != null) {
                final CheckinEngine ci = new CheckinEngine(client, this);

                final long start = System.currentTimeMillis();
                ci.uploadChanges(changes, false, getLocation() == WorkspaceLocation.LOCAL);
                log.debug(MessageFormat.format("total time for upload of {0} was {1} ms", //$NON-NLS-1$
                        changes.length, (System.currentTimeMillis() - start)));
            } else {
                log.debug("null changes (server side change selection), skipped upload"); //$NON-NLS-1$
            }
        } finally {
            TaskMonitorService.popTaskMonitor(true);
        }

        if (author == null) {
            author = VersionControlConstants.AUTHENTICATED_USER;
        }
        if (authorDisplayName == null) {
            authorDisplayName = UserNameUtil.getCurrentUserName();
            final String domainName = UserNameUtil.getCurrentUserDomain();
            if (!StringUtil.isNullOrEmpty(domainName)) {
                authorDisplayName = UserNameUtil.format(authorDisplayName, domainName);
            }
        }

        /*
         * Finally, create a Changeset and send it to the server to be
         * committed. It's important to pass "null" for the date so TFS 2010
         * and later do not require CheckinOther permissions (required to
         * set a specific date on a new changeset).
         */
        final Changeset changeset = new Changeset(null, comment, checkinNote, policyOverrideInfo, committer,
                committerDisplayName, null, -1, author, authorDisplayName, null);

        /*
         * Test one final time before the change set is fully committed.
         */
        if (monitor.isCanceled()) {
            // Caught in this method below.
            throw new CoreCancelException();
        }

        monitor.setCurrentWorkDescription(Messages.getString("Workspace.CheckinInNewChangeset")); //$NON-NLS-1$

        final AtomicReference<Failure[]> failures = new AtomicReference<Failure[]>();
        final AtomicReference<Failure[]> conflicts = new AtomicReference<Failure[]>();
        final boolean noAutoResolve = flags.contains(CheckinFlags.NO_AUTO_RESOLVE);

        final CheckinResult result;
        try {
            /*
             * If changes was null when this method was called, serverItems
             * will be null here, which causes the server to check in all
             * workspace changes.
             */
            result = getClient().getWebServiceLayer().checkIn(getName(), getOwnerName(), serverItems, changeset,
                    makeCheckinNotificationInfo(associatedWorkItems), flags, null, conflicts, failures, false,
                    0, client.mergeWithDefaultItemPropertyFilters(null));
        } catch (final ActionDeniedBySubscriberException e) {
            if (e.getSubscriberType().equals(BUILD_CHECKIN_SUBSCRIBER) && e.getStatusCode() == 1) {
                /*
                 * For ease of use, convert the
                 * ActionDeniedBySubscriberException into a stronger type,
                 * GatedCheckinException. This exception has helper
                 * properties and is typed in a way that customers expect.
                 * It is still an ActionDeniedBySubscriberException.
                 */
                throw new GatedCheckinException(e);
            } else {
                /*
                 * Some other subscriber has denied the decision point.
                 * Throw the ActionDeniedBySubscriberException verbatim.
                 */
                throw e;
            }
        }

        monitor.worked(10);

        changeset.setChangesetID(result.getChangeset());

        // Report any failures.
        reportCheckinConflictsAndThrow(result, conflicts.get(), failures.get(), noAutoResolve);

        /*
         * When the SetFileTimeToCheckin workspace option is set, then the
         * full checkin manifest is returned to the client in the form of
         * GetOperations, even in a server workspace. (In a server
         * workspace, the local version updates are still performed by the
         * server at the end of the CheckIn call.) We use this manifest to
         * set the check-in date on each item in the changeset, even
         * implicitly included missing parents and affected items of
         * recursive changes.
         */
        final TaskMonitor setFileTimeMonitor = monitor.newSubTaskMonitor(5);
        try {
            if (getOptions().contains(WorkspaceOptions.SET_FILE_TO_CHECKIN)) {
                final GetOperation[] updates = result.getLocalVersionUpdates();

                if (updates != null && updates.length > 0) {
                    setFileTimeMonitor.begin(Messages.getString("Workspace.SettingFileTime"), updates.length); //$NON-NLS-1$

                    for (final GetOperation getOp : updates) {
                        if (ItemType.FILE == getOp.getItemType() && null != getOp.getTargetLocalItem()
                                && new File(getOp.getTargetLocalItem()).exists()) {
                            setFileTimeMonitor.setCurrentWorkDescription(getOp.getTargetLocalItem());

                            try {
                                final FileSystemAttributes attributes = FileSystemUtils.getInstance()
                                        .getAttributes(getOp.getTargetLocalItem());
                                boolean restoreReadOnly = false;

                                /*
                                 * Temporarily remove the read-only flag so
                                 * we can modify the time (Windows requires
                                 * this).
                                 */
                                if (attributes.isReadOnly()) {
                                    attributes.setReadOnly(false);
                                    FileSystemUtils.getInstance().setAttributes(getOp.getTargetLocalItem(),
                                            attributes);
                                    restoreReadOnly = true;
                                }

                                new File(getOp.getTargetLocalItem())
                                        .setLastModified(result.getCreationDate().getTimeInMillis());

                                if (restoreReadOnly) {
                                    attributes.setReadOnly(true);
                                    FileSystemUtils.getInstance().setAttributes(getOp.getTargetLocalItem(),
                                            attributes);
                                }
                            } catch (final Exception e) {
                                client.getEventEngine().fireNonFatalError(
                                        new NonFatalErrorEvent(EventSource.newFromHere(), this, e));
                            }
                        }
                    }
                }
            }
        } finally {
            setFileTimeMonitor.done();
        }

        /*
         * If this is a server workspace, set files read-only.
         */
        final TaskMonitor makeReadOnlyMonitor = monitor.newSubTaskMonitor(5);
        try {
            if (changes != null && getLocation() == WorkspaceLocation.SERVER) {
                makeReadOnlyMonitor.begin(Messages.getString("Workspace.SettingReadOnly"), changes.length); //$NON-NLS-1$

                for (final PendingChange change : changes) {
                    if (change.getChangeType().contains(ChangeType.EDIT) && change.getLocalItem() != null
                            && new File(change.getLocalItem()).exists()) {
                        makeReadOnlyMonitor.setCurrentWorkDescription(change.getLocalItem());

                        try {
                            final FileSystemAttributes attributes = FileSystemUtils.getInstance()
                                    .getAttributes(change.getLocalItem());
                            if (!attributes.isSymbolicLink() && !attributes.isDirectory()) {
                                attributes.setReadOnly(true);
                                FileSystemUtils.getInstance().setAttributes(change.getLocalItem(), attributes);
                            }
                        } catch (final Exception e) {
                            client.getEventEngine().fireNonFatalError(
                                    new NonFatalErrorEvent(EventSource.newFromHere(), this, e));
                        }
                    } else {
                        // Skipping this one.
                        makeReadOnlyMonitor.setCurrentWorkDescription(""); //$NON-NLS-1$
                    }

                    makeReadOnlyMonitor.worked(1);
                }
            }
        } finally {
            makeReadOnlyMonitor.done();
        }

        monitor.setCurrentWorkDescription(Messages.getString("Workspace.NotifyingListeners")); //$NON-NLS-1$

        /*
         * Determine which pending changes were committed and which were
         * undone. Preserve the sorted order in the sublists.
         */

        PendingChange[] committedChangesArray = new PendingChange[0];
        PendingChange[] undoneChangesArray = new PendingChange[0];

        if (changes != null && changes.length > 0) {
            final Set<String> undoneServerItems = new TreeSet<String>(ServerPath.TOP_DOWN_COMPARATOR);

            for (final String undoneServerItem : result.getUndoneServerItems()) {
                undoneServerItems.add(undoneServerItem);
            }

            final List<PendingChange> undonePendingChanges = new ArrayList<PendingChange>(
                    undoneServerItems.size());
            final List<PendingChange> committedPendingChanges = new ArrayList<PendingChange>();

            for (final PendingChange change : changes) {
                if (undoneServerItems.contains(change.getServerItem())) {
                    undonePendingChanges.add(change);
                } else {
                    committedPendingChanges.add(change);
                }
            }

            committedChangesArray = committedPendingChanges
                    .toArray(new PendingChange[committedPendingChanges.size()]);
            undoneChangesArray = undonePendingChanges.toArray(new PendingChange[undonePendingChanges.size()]);
        }

        // Notify the user that the checkin iCheckinEvents complete.
        client.getEventEngine().fireCheckin(new CheckinEvent(EventSource.newFromHere(), this,
                result.getChangeset(), committedChangesArray, undoneChangesArray));

        Workstation.getCurrent(getClient().getConnection().getPersistenceStoreProvider())
                .notifyForWorkspace(this, Notification.VERSION_CONTROL_PENDING_CHANGES_CHANGED);

        monitor.worked(1);

        final int cset = changeset.getChangesetID();

        TaskMonitorService.pushTaskMonitor(monitor.newSubTaskMonitor(4));
        try {
            /*
             * Only update work items if we have a valid (non-0) changeset.
             * Changeset 0 indicates all the pending changes were undone on
             * the server.
             */
            if (cset != 0) {
                updateWorkItems(associatedWorkItems, cset, comment);
            }
        } finally {
            TaskMonitorService.popTaskMonitor(true);
        }

        // Remove any saved attempted checkin info.
        setLastSavedCheckin(buildEmptyLastSavedCheckin());

        success = true;
        return cset;
    } catch (final CanceledException e) {
        // Fire as non-fatal
        client.getEventEngine().fireNonFatalError(new NonFatalErrorEvent(EventSource.newFromHere(), this,
                new CoreCancelException(Messages.getString("Workspace.CheckinCancelled")))); //$NON-NLS-1$
        return 0;
    } catch (final CoreCancelException e) {
        // Convert to CanceledException and fire as non-fatal
        client.getEventEngine().fireNonFatalError(new NonFatalErrorEvent(EventSource.newFromHere(), this,
                new CanceledException(Messages.getString("Workspace.CheckinCancelled")))); //$NON-NLS-1$
        return 0;
    } finally {
        /*
         * If the checkin didn't succeed, save the info for the next
         * attempt. success will be false for expected things like gated
         * checkin and cancelation exceptions, and also for unexpected
         * exceptions.
         */
        if (!success) {
            updateLastSavedCheckin(comment, checkinNote, associatedWorkItems, policyOverrideInfo);
        }

        monitor.done();
    }
}

From source file:com.microsoft.tfs.core.clients.versioncontrol.soapextensions.Workspace.java

/**
 * Pend these changes for this workspace on the server.
 *
 * @param requests/* w  w w .  java  2 s  . c  om*/
 *        the requested changes to pend (must not be <code>null</code>)
 * @param getOptions
 *        options that affect how files on disk are treated during
 *        processing (must not be <code>null</code>)
 * @param pendOptions
 *        options that affect how items are pended (must not be
 *        <code>null</code>)
 * @param itemPropertyFilters
 *        a list of versioned item properties to return with each get
 *        operation (may be <code>null</code>)
 * @return the number of changes that were successfully processed by the
 *         server.
 */
private int pendChanges(final ChangeRequest[] requests, final GetOptions getOptions,
        final PendChangesOptions pendOptions, String[] itemPropertyFilters) {
    Check.notNull(requests, "requests"); //$NON-NLS-1$
    Check.notNull(getOptions, "getOptions"); //$NON-NLS-1$
    Check.notNull(pendOptions, "pendOptions"); //$NON-NLS-1$

    // Using web service directly so merge filters configured on client
    itemPropertyFilters = client.mergeWithDefaultItemPropertyFilters(itemPropertyFilters);

    client.getEventEngine()
            .fireOperationStarted(new PendOperationStartedEvent(EventSource.newFromHere(), this, requests));

    if (getClient().getServiceLevel().getValue() < WebServiceLevel.TFS_2012.getValue()) {
        if (hasPropertyChange(requests)) {
            client.getEventEngine().fireNonFatalError(new NonFatalErrorEvent(EventSource.newFromHere(), this,
                    new VersionControlException(Messages.getString("Workspace.PropertyNotSupportedText")))); //$NON-NLS-1$
        }
    }

    int ret = 0;
    try {
        SupportedFeatures features = SupportedFeatures.ALL;

        /*
         * If the get operation "Force Checkout Local Version" is set, we do
         * not advertise to the server that we support get latest on
         * checkout. Presumably, there may be a state where the server
         * wishes to update us to the local version and this explicitly
         * stops that.
         */
        if (pendOptions.contains(PendChangesOptions.FORCE_CHECK_OUT_LOCAL_VERSION)) {
            features = features.remove(SupportedFeatures.GET_LATEST_ON_CHECKOUT);
        }

        final AtomicReference<Failure[]> failures = new AtomicReference<Failure[]>();
        final AtomicBoolean onlineOperation = new AtomicBoolean();
        final AtomicReference<ChangePendedFlags> changePendedFlags = new AtomicReference<ChangePendedFlags>();

        final GetOperation[] operations = client.getWebServiceLayer().pendChanges(getName(), getOwnerName(),
                requests, pendOptions, features, failures, itemPropertyFilters, null, true, onlineOperation,
                changePendedFlags);

        // Get any required files.
        if (operations.length > 0) {

            /*
             * The TFS server (as of TFS 2013 QU1) provides in the response
             * only properties saved in the server's database, i.e. already
             * checked in. Thus, to process the executable bit and symlinks
             * using properties mechanism correctly in the client file
             * system, we have to merge properties received in the response
             * with those submitted in the change request.
             *
             * Note that for the local workspaces it's already done in the
             * LocalDataAccessLayer class.
             */
            if (WorkspaceLocation.SERVER == this.getLocation()
                    && getClient().getServiceLevel().getValue() >= WebServiceLevel.TFS_2012.getValue()) {
                for (final ChangeRequest request : requests) {
                    final PropertyValue[] requestProperties = request.getProperties();
                    if (requestProperties != null) {
                        final GetOperation operation = findMatchingOperation(operations, request);

                        if (operation != null) {
                            final PropertyValue[] operationProperties = operation.getPropertyValues();

                            if (operationProperties != null) {
                                operation.setPropertyValues(PropertyUtils
                                        .mergePendingValues(operationProperties, requestProperties));
                            }
                        }
                    }
                }
            }

            final GetEngine getEngine = new GetEngine(client);

            getEngine.processGetOperations(this, ProcessType.PEND, requests[0].getRequestType(),
                    new GetOperation[][] { operations }, getOptions, false, onlineOperation.get(),
                    changePendedFlags.get());

            // Return the number of operations that were successful.
            ret = operations.length;
        }

        if (changePendedFlags.get().contains(ChangePendedFlags.WORKING_FOLDER_MAPPINGS_UPDATED)) {
            invalidateMappings();
        }

        /*
         * If it was requested by the caller, strip out any Failure objects
         * from the failure set which are of type ItemNotFoundException.
         */
        if (failures.get() != null && failures.get().length > 0
                && pendOptions.contains(PendChangesOptions.SUPPRESS_ITEM_NOT_FOUND_FAILURES)) {
            final List<Failure> otherFailures = new ArrayList<Failure>();

            for (final Failure f : failures.get()) {
                if (f.getCode() == null || !f.getCode().equals(FailureCodes.ITEM_EXISTS_EXCEPTION)) {
                    otherFailures.add(f);
                }
            }

            failures.set(otherFailures.toArray(new Failure[otherFailures.size()]));
        }

        client.reportFailures(this, failures.get());

    } finally {
        client.getEventEngine().fireOperationCompleted(
                new PendOperationCompletedEvent(EventSource.newFromHere(), this, requests));

        Workstation.getCurrent(getClient().getConnection().getPersistenceStoreProvider())
                .notifyForWorkspace(this, Notification.VERSION_CONTROL_PENDING_CHANGES_CHANGED);
    }

    return ret;
}

From source file:de.schildbach.pte.AbstractEfaProvider.java

private QueryDeparturesResult xsltDepartureMonitorRequest(final String stationId, final @Nullable Date time,
        final int maxDepartures, final boolean equivs) throws IOException {
    final HttpUrl.Builder url = departureMonitorEndpoint.newBuilder();
    appendXsltDepartureMonitorRequestParameters(url, stationId, time, maxDepartures, equivs);
    final AtomicReference<QueryDeparturesResult> result = new AtomicReference<>();

    final HttpClient.Callback callback = new HttpClient.Callback() {
        @Override// w ww .  ja v  a  2s.  c  o m
        public void onSuccessful(final CharSequence bodyPeek, final ResponseBody body) throws IOException {
            try {
                final XmlPullParser pp = parserFactory.newPullParser();
                pp.setInput(body.byteStream(), null); // Read encoding from XML declaration
                final ResultHeader header = enterItdRequest(pp);

                final QueryDeparturesResult r = new QueryDeparturesResult(header);

                XmlPullUtil.enter(pp, "itdDepartureMonitorRequest");
                XmlPullUtil.optSkipMultiple(pp, "itdMessage");

                final String nameState = processItdOdv(pp, "dm", new ProcessItdOdvCallback() {
                    @Override
                    public void location(final String nameState, final Location location,
                            final int matchQuality) {
                        if (location.type == LocationType.STATION)
                            if (findStationDepartures(r.stationDepartures, location.id) == null)
                                r.stationDepartures.add(new StationDepartures(location,
                                        new LinkedList<Departure>(), new LinkedList<LineDestination>()));
                    }
                });

                if ("notidentified".equals(nameState) || "list".equals(nameState)) {
                    result.set(new QueryDeparturesResult(header, QueryDeparturesResult.Status.INVALID_STATION));
                    return;
                }

                XmlPullUtil.optSkip(pp, "itdDateTime");

                XmlPullUtil.optSkip(pp, "itdDMDateTime");

                XmlPullUtil.optSkip(pp, "itdDateRange");

                XmlPullUtil.optSkip(pp, "itdTripOptions");

                XmlPullUtil.optSkip(pp, "itdMessage");

                if (XmlPullUtil.test(pp, "itdServingLines")) {
                    if (!pp.isEmptyElementTag()) {
                        XmlPullUtil.enter(pp, "itdServingLines");
                        while (XmlPullUtil.test(pp, "itdServingLine")) {
                            final String assignedStopId = XmlPullUtil.optAttr(pp, "assignedStopID", null);
                            final LineDestinationAndCancelled lineDestinationAndCancelled = processItdServingLine(
                                    pp);
                            final LineDestination lineDestination = new LineDestination(
                                    lineDestinationAndCancelled.line, lineDestinationAndCancelled.destination);

                            StationDepartures assignedStationDepartures;
                            if (assignedStopId == null)
                                assignedStationDepartures = r.stationDepartures.get(0);
                            else
                                assignedStationDepartures = findStationDepartures(r.stationDepartures,
                                        assignedStopId);

                            if (assignedStationDepartures == null)
                                assignedStationDepartures = new StationDepartures(
                                        new Location(LocationType.STATION, assignedStopId),
                                        new LinkedList<Departure>(), new LinkedList<LineDestination>());

                            final List<LineDestination> assignedStationDeparturesLines = checkNotNull(
                                    assignedStationDepartures.lines);
                            if (!assignedStationDeparturesLines.contains(lineDestination))
                                assignedStationDeparturesLines.add(lineDestination);
                        }
                        XmlPullUtil.skipExit(pp, "itdServingLines");
                    } else {
                        XmlPullUtil.next(pp);
                    }
                } else {
                    result.set(new QueryDeparturesResult(header, QueryDeparturesResult.Status.INVALID_STATION));
                    return;
                }

                XmlPullUtil.require(pp, "itdDepartureList");
                if (XmlPullUtil.optEnter(pp, "itdDepartureList")) {
                    final Calendar plannedDepartureTime = new GregorianCalendar(timeZone);
                    final Calendar predictedDepartureTime = new GregorianCalendar(timeZone);

                    while (XmlPullUtil.test(pp, "itdDeparture")) {
                        final String assignedStopId = XmlPullUtil.attr(pp, "stopID");

                        StationDepartures assignedStationDepartures = findStationDepartures(r.stationDepartures,
                                assignedStopId);
                        if (assignedStationDepartures == null) {
                            final Point coord = processCoordAttr(pp);

                            // final String name = normalizeLocationName(XmlPullUtil.attr(pp, "nameWO"));

                            assignedStationDepartures = new StationDepartures(
                                    new Location(LocationType.STATION, assignedStopId, coord),
                                    new LinkedList<Departure>(), new LinkedList<LineDestination>());
                        }

                        final Position position = parsePosition(XmlPullUtil.optAttr(pp, "platformName", null));

                        XmlPullUtil.enter(pp, "itdDeparture");

                        XmlPullUtil.require(pp, "itdDateTime");
                        plannedDepartureTime.clear();
                        processItdDateTime(pp, plannedDepartureTime);

                        predictedDepartureTime.clear();
                        if (XmlPullUtil.test(pp, "itdRTDateTime"))
                            processItdDateTime(pp, predictedDepartureTime);

                        XmlPullUtil.optSkip(pp, "itdFrequencyInfo");

                        XmlPullUtil.require(pp, "itdServingLine");
                        final boolean isRealtime = XmlPullUtil.attr(pp, "realtime").equals("1");
                        final LineDestinationAndCancelled lineDestinationAndCancelled = processItdServingLine(
                                pp);

                        if (isRealtime && !predictedDepartureTime.isSet(Calendar.HOUR_OF_DAY))
                            predictedDepartureTime.setTimeInMillis(plannedDepartureTime.getTimeInMillis());

                        XmlPullUtil.skipExit(pp, "itdDeparture");

                        if (!lineDestinationAndCancelled.cancelled) {
                            final Departure departure = new Departure(plannedDepartureTime.getTime(),
                                    predictedDepartureTime.isSet(Calendar.HOUR_OF_DAY)
                                            ? predictedDepartureTime.getTime()
                                            : null,
                                    lineDestinationAndCancelled.line, position,
                                    lineDestinationAndCancelled.destination, null, null);
                            assignedStationDepartures.departures.add(departure);
                        }
                    }

                    XmlPullUtil.skipExit(pp, "itdDepartureList");
                }

                result.set(r);
            } catch (final XmlPullParserException x) {
                throw new ParserException("cannot parse xml: " + bodyPeek, x);
            }
        }
    };

    if (httpPost)
        httpClient.getInputStream(callback, url.build(), url.build().encodedQuery(),
                "application/x-www-form-urlencoded", httpReferer);
    else
        httpClient.getInputStream(callback, url.build(), httpReferer);

    return result.get();
}

From source file:de.schildbach.pte.AbstractHafasLegacyProvider.java

protected final QueryDeparturesResult xmlStationBoard(final HttpUrl url, final String stationId)
        throws IOException {
    final String normalizedStationId = normalizeStationId(stationId);
    final AtomicReference<QueryDeparturesResult> result = new AtomicReference<>();

    httpClient.getInputStream(new HttpClient.Callback() {

        @Override//from  w  ww.  ja v a 2  s.  com
        public void onSuccessful(final CharSequence bodyPeek, final ResponseBody body) throws IOException {
            StringReplaceReader reader = null;
            String firstChars = null;

            // work around unparsable XML
            reader = new StringReplaceReader(body.charStream(), " & ", " &amp; ");
            reader.replace("<b>", " ");
            reader.replace("</b>", " ");
            reader.replace("<u>", " ");
            reader.replace("</u>", " ");
            reader.replace("<i>", " ");
            reader.replace("</i>", " ");
            reader.replace("<br />", " ");
            reader.replace(" ->", " &#x2192;"); // right arrow
            reader.replace(" <-", " &#x2190;"); // left arrow
            reader.replace(" <> ", " &#x2194; "); // left-right arrow
            addCustomReplaces(reader);

            try {
                final XmlPullParserFactory factory = XmlPullParserFactory
                        .newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
                final XmlPullParser pp = factory.newPullParser();
                pp.setInput(reader);

                pp.nextTag();

                final ResultHeader header = new ResultHeader(network, SERVER_PRODUCT);
                final QueryDeparturesResult r = new QueryDeparturesResult(header);

                if (XmlPullUtil.test(pp, "Err")) {
                    final String code = XmlPullUtil.attr(pp, "code");
                    final String text = XmlPullUtil.attr(pp, "text");

                    if (code.equals("H730")) {
                        result.set(new QueryDeparturesResult(header,
                                QueryDeparturesResult.Status.INVALID_STATION));
                        return;
                    }
                    if (code.equals("H890")) {
                        r.stationDepartures.add(
                                new StationDepartures(new Location(LocationType.STATION, normalizedStationId),
                                        Collections.<Departure>emptyList(), null));
                        result.set(r);
                        return;
                    }
                    throw new IllegalArgumentException("unknown error " + code + ", " + text);
                }

                String[] stationPlaceAndName = null;

                if (stationBoardHasStationTable)
                    XmlPullUtil.enter(pp, "StationTable");
                else
                    checkState(!XmlPullUtil.test(pp, "StationTable"));

                if (stationBoardHasLocation) {
                    XmlPullUtil.require(pp, "St");

                    final String evaId = XmlPullUtil.attr(pp, "evaId");
                    if (evaId != null) {
                        if (!evaId.equals(normalizedStationId))
                            throw new IllegalStateException(
                                    "stationId: " + normalizedStationId + ", evaId: " + evaId);

                        final String name = XmlPullUtil.attr(pp, "name");
                        if (name != null)
                            stationPlaceAndName = splitStationName(name.trim());
                    }
                    XmlPullUtil.requireSkip(pp, "St");
                } else {
                    checkState(!XmlPullUtil.test(pp, "St"));
                }

                while (XmlPullUtil.test(pp, "Journey")) {
                    final String fpTime = XmlPullUtil.attr(pp, "fpTime");
                    final String fpDate = XmlPullUtil.attr(pp, "fpDate");
                    final String delay = XmlPullUtil.attr(pp, "delay");
                    final String eDelay = XmlPullUtil.optAttr(pp, "e_delay", null);
                    final String platform = XmlPullUtil.optAttr(pp, "platform", null);
                    // TODO newpl
                    final String targetLoc = XmlPullUtil.optAttr(pp, "targetLoc", null);
                    // TODO hafasname
                    final String dirnr = XmlPullUtil.optAttr(pp, "dirnr", null);
                    final String prod = XmlPullUtil.attr(pp, "prod");
                    final String classStr = XmlPullUtil.optAttr(pp, "class", null);
                    final String dir = XmlPullUtil.optAttr(pp, "dir", null);
                    final String capacityStr = XmlPullUtil.optAttr(pp, "capacity", null);
                    final String depStation = XmlPullUtil.optAttr(pp, "depStation", null);
                    final String delayReason = XmlPullUtil.optAttr(pp, "delayReason", null);
                    // TODO is_reachable
                    // TODO disableTrainInfo
                    // TODO lineFG/lineBG (ZVV)
                    final String administration = normalizeLineAdministration(
                            XmlPullUtil.optAttr(pp, "administration", null));

                    if (!"cancel".equals(delay) && !"cancel".equals(eDelay)) {
                        final Calendar plannedTime = new GregorianCalendar(timeZone);
                        plannedTime.clear();
                        parseXmlStationBoardDate(plannedTime, fpDate);
                        parseXmlStationBoardTime(plannedTime, fpTime);

                        final Calendar predictedTime;
                        if (eDelay != null) {
                            predictedTime = new GregorianCalendar(timeZone);
                            predictedTime.setTimeInMillis(plannedTime.getTimeInMillis());
                            predictedTime.add(Calendar.MINUTE, Integer.parseInt(eDelay));
                        } else if (delay != null) {
                            final Matcher m = P_XML_STATION_BOARD_DELAY.matcher(delay);
                            if (m.matches()) {
                                if (m.group(1) != null) {
                                    predictedTime = new GregorianCalendar(timeZone);
                                    predictedTime.setTimeInMillis(plannedTime.getTimeInMillis());
                                    predictedTime.add(Calendar.MINUTE, Integer.parseInt(m.group(1)));
                                } else {
                                    predictedTime = null;
                                }
                            } else {
                                throw new RuntimeException("cannot parse delay: '" + delay + "'");
                            }
                        } else {
                            predictedTime = null;
                        }

                        final Position position = parsePosition(ParserUtils.resolveEntities(platform));

                        final String destinationName;
                        if (dir != null)
                            destinationName = dir.trim();
                        else if (targetLoc != null)
                            destinationName = targetLoc.trim();
                        else
                            destinationName = null;

                        final Location destination;
                        if (dirnr != null) {
                            final String[] destinationPlaceAndName = splitStationName(destinationName);
                            destination = new Location(LocationType.STATION, dirnr, destinationPlaceAndName[0],
                                    destinationPlaceAndName[1]);
                        } else {
                            destination = new Location(LocationType.ANY, null, null, destinationName);
                        }

                        final Line prodLine = parseLineAndType(prod);
                        final Line line;
                        if (classStr != null) {
                            final Product product = intToProduct(Integer.parseInt(classStr));
                            if (product == null)
                                throw new IllegalArgumentException();
                            // could check for type consistency here
                            final Set<Attr> attrs = prodLine.attrs;
                            if (attrs != null)
                                line = newLine(administration, product, prodLine.label, null,
                                        attrs.toArray(new Line.Attr[0]));
                            else
                                line = newLine(administration, product, prodLine.label, null);
                        } else {
                            final Set<Attr> attrs = prodLine.attrs;
                            if (attrs != null)
                                line = newLine(administration, prodLine.product, prodLine.label, null,
                                        attrs.toArray(new Line.Attr[0]));
                            else
                                line = newLine(administration, prodLine.product, prodLine.label, null);
                        }

                        final int[] capacity;
                        if (capacityStr != null && !"0|0".equals(capacityStr)) {
                            final String[] capacityParts = capacityStr.split("\\|");
                            capacity = new int[] { Integer.parseInt(capacityParts[0]),
                                    Integer.parseInt(capacityParts[1]) };
                        } else {
                            capacity = null;
                        }

                        final String message;
                        if (delayReason != null) {
                            final String msg = delayReason.trim();
                            message = msg.length() > 0 ? msg : null;
                        } else {
                            message = null;
                        }

                        final Departure departure = new Departure(plannedTime.getTime(),
                                predictedTime != null ? predictedTime.getTime() : null, line, position,
                                destination, capacity, message);

                        final Location location;
                        if (!stationBoardCanDoEquivs || depStation == null) {
                            location = new Location(LocationType.STATION, normalizedStationId,
                                    stationPlaceAndName != null ? stationPlaceAndName[0] : null,
                                    stationPlaceAndName != null ? stationPlaceAndName[1] : null);
                        } else {
                            final String[] depPlaceAndName = splitStationName(depStation);
                            location = new Location(LocationType.STATION, null, depPlaceAndName[0],
                                    depPlaceAndName[1]);
                        }

                        StationDepartures stationDepartures = findStationDepartures(r.stationDepartures,
                                location);
                        if (stationDepartures == null) {
                            stationDepartures = new StationDepartures(location, new ArrayList<Departure>(8),
                                    null);
                            r.stationDepartures.add(stationDepartures);
                        }

                        stationDepartures.departures.add(departure);
                    }

                    XmlPullUtil.requireSkip(pp, "Journey");
                }

                if (stationBoardHasStationTable)
                    XmlPullUtil.exit(pp, "StationTable");

                XmlPullUtil.requireEndDocument(pp);

                // sort departures
                for (final StationDepartures stationDepartures : r.stationDepartures)
                    Collections.sort(stationDepartures.departures, Departure.TIME_COMPARATOR);

                result.set(r);
            } catch (final XmlPullParserException x) {
                throw new ParserException("cannot parse xml: " + firstChars, x);
            }
        }
    }, url);

    return result.get();
}

From source file:de.schildbach.pte.AbstractHafasLegacyProvider.java

private QueryTripsResult queryTripsXml(final Context previousContext, final boolean later,
        final CharSequence conReq, final Location from, final @Nullable Location via, final Location to)
        throws IOException {
    final String request = wrapReqC(conReq, null);
    final HttpUrl endpoint = extXmlEndpoint != null ? extXmlEndpoint
            : queryEndpoint.newBuilder().addPathSegment(apiLanguage).build();
    final AtomicReference<QueryTripsResult> result = new AtomicReference<>();
    httpClient.getInputStream(new HttpClient.Callback() {
        @Override//www.  j a  v  a  2  s .c o  m
        public void onSuccessful(final CharSequence bodyPeek, final ResponseBody body) throws IOException {
            try {
                final XmlPullParserFactory factory = XmlPullParserFactory
                        .newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
                final XmlPullParser pp = factory.newPullParser();
                pp.setInput(body.charStream());

                XmlPullUtil.require(pp, "ResC");
                final String product = XmlPullUtil.attr(pp, "prod").split(" ")[0];
                final ResultHeader header = new ResultHeader(network, SERVER_PRODUCT, product, null, 0, null);
                XmlPullUtil.enter(pp, "ResC");

                if (XmlPullUtil.test(pp, "Err")) {
                    final String code = XmlPullUtil.attr(pp, "code");
                    if (code.equals("I3")) {
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.INVALID_DATE));
                        return;
                    }
                    if (code.equals("F1")) {
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.SERVICE_DOWN));
                        return;
                    }
                    throw new IllegalStateException("error " + code + " " + XmlPullUtil.attr(pp, "text"));
                }

                XmlPullUtil.enter(pp, "ConRes");

                if (XmlPullUtil.test(pp, "Err")) {
                    final String code = XmlPullUtil.attr(pp, "code");
                    log.debug("Hafas error: {}", code);
                    if (code.equals("K9260")) {
                        // Unknown departure station
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.UNKNOWN_FROM));
                        return;
                    }
                    if (code.equals("K9280")) {
                        // Unknown intermediate station
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.UNKNOWN_VIA));
                        return;
                    }
                    if (code.equals("K9300")) {
                        // Unknown arrival station
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.UNKNOWN_TO));
                        return;
                    }
                    if (code.equals("K9360")) {
                        // Date outside of the timetable period
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.INVALID_DATE));
                        return;
                    }
                    if (code.equals("K9380")) {
                        // Dep./Arr./Intermed. or equivalent station defined more than once
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.TOO_CLOSE));
                        return;
                    }
                    if (code.equals("K895")) {
                        // Departure/Arrival are too near
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.TOO_CLOSE));
                        return;
                    }
                    if (code.equals("K9220")) {
                        // Nearby to the given address stations could not be found
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.UNRESOLVABLE_ADDRESS));
                        return;
                    }
                    if (code.equals("K9240")) {
                        // Internal error
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.SERVICE_DOWN));
                        return;
                    }
                    if (code.equals("K890")) {
                        // No connections found
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.NO_TRIPS));
                        return;
                    }
                    if (code.equals("K891")) {
                        // No route found (try entering an intermediate station)
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.NO_TRIPS));
                        return;
                    }
                    if (code.equals("K899")) {
                        // An error occurred
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.SERVICE_DOWN));
                        return;
                    }
                    if (code.equals("K1:890")) {
                        // Unsuccessful or incomplete search (direction: forward)
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.NO_TRIPS));
                        return;
                    }
                    if (code.equals("K2:890")) {
                        // Unsuccessful or incomplete search (direction: backward)
                        result.set(new QueryTripsResult(header, QueryTripsResult.Status.NO_TRIPS));
                        return;
                    }
                    throw new IllegalStateException("error " + code + " " + XmlPullUtil.attr(pp, "text"));
                }

                // H9380 Dep./Arr./Intermed. or equivalent stations defined more than once
                // H9360 Error in data field
                // H9320 The input is incorrect or incomplete
                // H9300 Unknown arrival station
                // H9280 Unknown intermediate station
                // H9260 Unknown departure station
                // H9250 Part inquiry interrupted
                // H9240 Unsuccessful search
                // H9230 An internal error occurred
                // H9220 Nearby to the given address stations could not be found
                // H900 Unsuccessful or incomplete search (timetable change)
                // H892 Inquiry too complex (try entering less intermediate stations)
                // H891 No route found (try entering an intermediate station)
                // H890 Unsuccessful search.
                // H500 Because of too many trains the connection is not complete
                // H460 One or more stops are passed through multiple times.
                // H455 Prolonged stop
                // H410 Display may be incomplete due to change of timetable
                // H390 Departure/Arrival replaced by an equivalent station
                // H895 Departure/Arrival are too near
                // H899 Unsuccessful or incomplete search (timetable change

                final String c = XmlPullUtil.optValueTag(pp, "ConResCtxt", null);
                final Context context;
                if (previousContext == null)
                    context = new Context(c, c, 0);
                else if (later)
                    context = new Context(c, previousContext.earlierContext, previousContext.sequence + 1);
                else
                    context = new Context(previousContext.laterContext, c, previousContext.sequence + 1);

                XmlPullUtil.enter(pp, "ConnectionList");

                final List<Trip> trips = new ArrayList<>();

                while (XmlPullUtil.test(pp, "Connection")) {
                    final String id = context.sequence + "/" + XmlPullUtil.attr(pp, "id");

                    XmlPullUtil.enter(pp, "Connection");
                    while (pp.getName().equals("RtStateList"))
                        XmlPullUtil.next(pp);
                    XmlPullUtil.enter(pp, "Overview");

                    final Calendar currentDate = new GregorianCalendar(timeZone);
                    currentDate.clear();
                    parseDate(currentDate, XmlPullUtil.valueTag(pp, "Date"));
                    XmlPullUtil.enter(pp, "Departure");
                    XmlPullUtil.enter(pp, "BasicStop");
                    while (pp.getName().equals("StAttrList"))
                        XmlPullUtil.next(pp);
                    final Location departureLocation = parseLocation(pp);
                    XmlPullUtil.enter(pp, "Dep");
                    XmlPullUtil.skipExit(pp, "Dep");
                    final int[] capacity;
                    if (XmlPullUtil.test(pp, "StopPrognosis")) {
                        XmlPullUtil.enter(pp, "StopPrognosis");
                        XmlPullUtil.optSkip(pp, "Arr");
                        XmlPullUtil.optSkip(pp, "Dep");
                        XmlPullUtil.enter(pp, "Status");
                        XmlPullUtil.skipExit(pp, "Status");
                        final int capacity1st = Integer
                                .parseInt(XmlPullUtil.optValueTag(pp, "Capacity1st", "0"));
                        final int capacity2nd = Integer
                                .parseInt(XmlPullUtil.optValueTag(pp, "Capacity2nd", "0"));
                        if (capacity1st > 0 || capacity2nd > 0)
                            capacity = new int[] { capacity1st, capacity2nd };
                        else
                            capacity = null;
                        XmlPullUtil.skipExit(pp, "StopPrognosis");
                    } else {
                        capacity = null;
                    }
                    XmlPullUtil.skipExit(pp, "BasicStop");
                    XmlPullUtil.skipExit(pp, "Departure");

                    XmlPullUtil.enter(pp, "Arrival");
                    XmlPullUtil.enter(pp, "BasicStop");
                    while (pp.getName().equals("StAttrList"))
                        XmlPullUtil.next(pp);
                    final Location arrivalLocation = parseLocation(pp);
                    XmlPullUtil.skipExit(pp, "BasicStop");
                    XmlPullUtil.skipExit(pp, "Arrival");

                    final int numTransfers = Integer.parseInt(XmlPullUtil.valueTag(pp, "Transfers"));

                    XmlPullUtil.skipExit(pp, "Overview");

                    final List<Trip.Leg> legs = new ArrayList<>(4);

                    XmlPullUtil.enter(pp, "ConSectionList");

                    final Calendar time = new GregorianCalendar(timeZone);

                    while (XmlPullUtil.test(pp, "ConSection")) {
                        XmlPullUtil.enter(pp, "ConSection");

                        // departure
                        XmlPullUtil.enter(pp, "Departure");
                        XmlPullUtil.enter(pp, "BasicStop");
                        while (pp.getName().equals("StAttrList"))
                            XmlPullUtil.next(pp);
                        final Location sectionDepartureLocation = parseLocation(pp);

                        XmlPullUtil.optSkip(pp, "Arr");
                        XmlPullUtil.enter(pp, "Dep");
                        time.setTimeInMillis(currentDate.getTimeInMillis());
                        parseTime(time, XmlPullUtil.valueTag(pp, "Time"));
                        final Date departureTime = time.getTime();
                        final Position departurePos = parsePlatform(pp);
                        XmlPullUtil.skipExit(pp, "Dep");

                        XmlPullUtil.skipExit(pp, "BasicStop");
                        XmlPullUtil.skipExit(pp, "Departure");

                        // journey
                        final Line line;
                        Location destination = null;

                        List<Stop> intermediateStops = null;

                        final String tag = pp.getName();
                        if (tag.equals("Journey")) {
                            XmlPullUtil.enter(pp, "Journey");
                            while (pp.getName().equals("JHandle"))
                                XmlPullUtil.next(pp);
                            XmlPullUtil.enter(pp, "JourneyAttributeList");
                            boolean wheelchairAccess = false;
                            String name = null;
                            String category = null;
                            String shortCategory = null;
                            while (XmlPullUtil.test(pp, "JourneyAttribute")) {
                                XmlPullUtil.enter(pp, "JourneyAttribute");
                                XmlPullUtil.require(pp, "Attribute");
                                final String attrName = XmlPullUtil.attr(pp, "type");
                                final String code = XmlPullUtil.optAttr(pp, "code", null);
                                XmlPullUtil.enter(pp, "Attribute");
                                final Map<String, String> attributeVariants = parseAttributeVariants(pp);
                                XmlPullUtil.skipExit(pp, "Attribute");
                                XmlPullUtil.skipExit(pp, "JourneyAttribute");

                                if ("bf".equals(code)) {
                                    wheelchairAccess = true;
                                } else if ("NAME".equals(attrName)) {
                                    name = attributeVariants.get("NORMAL");
                                } else if ("CATEGORY".equals(attrName)) {
                                    shortCategory = attributeVariants.get("SHORT");
                                    category = attributeVariants.get("NORMAL");
                                    // longCategory = attributeVariants.get("LONG");
                                } else if ("DIRECTION".equals(attrName)) {
                                    final String[] destinationPlaceAndName = splitStationName(
                                            attributeVariants.get("NORMAL"));
                                    destination = new Location(LocationType.ANY, null,
                                            destinationPlaceAndName[0], destinationPlaceAndName[1]);
                                }
                            }
                            XmlPullUtil.skipExit(pp, "JourneyAttributeList");

                            if (XmlPullUtil.test(pp, "PassList")) {
                                intermediateStops = new LinkedList<>();

                                XmlPullUtil.enter(pp, "PassList");
                                while (XmlPullUtil.test(pp, "BasicStop")) {
                                    XmlPullUtil.enter(pp, "BasicStop");
                                    while (XmlPullUtil.test(pp, "StAttrList"))
                                        XmlPullUtil.next(pp);
                                    final Location location = parseLocation(pp);
                                    if (location.id != sectionDepartureLocation.id) {
                                        Date stopArrivalTime = null;
                                        Date stopDepartureTime = null;
                                        Position stopArrivalPosition = null;
                                        Position stopDeparturePosition = null;

                                        if (XmlPullUtil.test(pp, "Arr")) {
                                            XmlPullUtil.enter(pp, "Arr");
                                            time.setTimeInMillis(currentDate.getTimeInMillis());
                                            parseTime(time, XmlPullUtil.valueTag(pp, "Time"));
                                            stopArrivalTime = time.getTime();
                                            stopArrivalPosition = parsePlatform(pp);
                                            XmlPullUtil.skipExit(pp, "Arr");
                                        }

                                        if (XmlPullUtil.test(pp, "Dep")) {
                                            XmlPullUtil.enter(pp, "Dep");
                                            time.setTimeInMillis(currentDate.getTimeInMillis());
                                            parseTime(time, XmlPullUtil.valueTag(pp, "Time"));
                                            stopDepartureTime = time.getTime();
                                            stopDeparturePosition = parsePlatform(pp);
                                            XmlPullUtil.skipExit(pp, "Dep");
                                        }

                                        intermediateStops.add(new Stop(location, stopArrivalTime,
                                                stopArrivalPosition, stopDepartureTime, stopDeparturePosition));
                                    }
                                    XmlPullUtil.skipExit(pp, "BasicStop");
                                }

                                XmlPullUtil.skipExit(pp, "PassList");
                            }

                            XmlPullUtil.skipExit(pp, "Journey");

                            if (category == null)
                                category = shortCategory;

                            line = parseLine(category, name, wheelchairAccess);
                        } else if (tag.equals("Walk") || tag.equals("Transfer") || tag.equals("GisRoute")) {
                            XmlPullUtil.enter(pp);
                            XmlPullUtil.enter(pp, "Duration");
                            XmlPullUtil.skipExit(pp, "Duration");
                            XmlPullUtil.skipExit(pp);

                            line = null;
                        } else {
                            throw new IllegalStateException("cannot handle: " + pp.getName());
                        }

                        // polyline
                        final List<Point> path;
                        if (XmlPullUtil.test(pp, "Polyline")) {
                            path = new LinkedList<>();
                            XmlPullUtil.enter(pp, "Polyline");
                            while (XmlPullUtil.test(pp, "Point")) {
                                final int x = XmlPullUtil.intAttr(pp, "x");
                                final int y = XmlPullUtil.intAttr(pp, "y");
                                path.add(new Point(y, x));
                                XmlPullUtil.next(pp);
                            }
                            XmlPullUtil.skipExit(pp, "Polyline");
                        } else {
                            path = null;
                        }

                        // arrival
                        XmlPullUtil.enter(pp, "Arrival");
                        XmlPullUtil.enter(pp, "BasicStop");
                        while (pp.getName().equals("StAttrList"))
                            XmlPullUtil.next(pp);
                        final Location sectionArrivalLocation = parseLocation(pp);
                        XmlPullUtil.enter(pp, "Arr");
                        time.setTimeInMillis(currentDate.getTimeInMillis());
                        parseTime(time, XmlPullUtil.valueTag(pp, "Time"));
                        final Date arrivalTime = time.getTime();
                        final Position arrivalPos = parsePlatform(pp);
                        XmlPullUtil.skipExit(pp, "Arr");

                        XmlPullUtil.skipExit(pp, "BasicStop");
                        XmlPullUtil.skipExit(pp, "Arrival");

                        // remove last intermediate
                        if (intermediateStops != null)
                            if (!intermediateStops.isEmpty())
                                if (!intermediateStops.get(intermediateStops.size() - 1).location
                                        .equals(sectionArrivalLocation))
                                    intermediateStops.remove(intermediateStops.size() - 1);

                        XmlPullUtil.skipExit(pp, "ConSection");

                        if (line != null) {
                            final Stop departure = new Stop(sectionDepartureLocation, true, departureTime, null,
                                    departurePos, null);
                            final Stop arrival = new Stop(sectionArrivalLocation, false, arrivalTime, null,
                                    arrivalPos, null);

                            legs.add(new Trip.Public(line, destination, departure, arrival, intermediateStops,
                                    path, null));
                        } else {
                            if (legs.size() > 0 && legs.get(legs.size() - 1) instanceof Trip.Individual) {
                                final Trip.Individual lastIndividualLeg = (Trip.Individual) legs
                                        .remove(legs.size() - 1);
                                legs.add(new Trip.Individual(Trip.Individual.Type.WALK,
                                        lastIndividualLeg.departure, lastIndividualLeg.departureTime,
                                        sectionArrivalLocation, arrivalTime, null, 0));
                            } else {
                                legs.add(
                                        new Trip.Individual(Trip.Individual.Type.WALK, sectionDepartureLocation,
                                                departureTime, sectionArrivalLocation, arrivalTime, null, 0));
                            }
                        }
                    }

                    XmlPullUtil.skipExit(pp, "ConSectionList");

                    XmlPullUtil.skipExit(pp, "Connection");

                    trips.add(new Trip(id, departureLocation, arrivalLocation, legs, null, capacity,
                            numTransfers));
                }

                XmlPullUtil.skipExit(pp, "ConnectionList");

                result.set(new QueryTripsResult(header, null, from, via, to, context, trips));
            } catch (final XmlPullParserException x) {
                throw new ParserException("cannot parse xml: " + bodyPeek, x);
            }
        }
    }, endpoint, request, "application/xml", null);

    return result.get();
}

From source file:de.schildbach.pte.AbstractHafasLegacyProvider.java

private QueryTripsResult queryTripsBinary(final HttpUrl url, final Location from, final @Nullable Location via,
        final Location to, final int expectedBufferSize) throws IOException {
    /*//from w w  w. ja  v a2 s .c  o  m
     * Many thanks to Malte Starostik and Robert, who helped a lot with analyzing this API!
     */

    final AtomicReference<QueryTripsResult> result = new AtomicReference<>();

    httpClient.getInputStream(new HttpClient.Callback() {
        @Override
        public void onSuccessful(final CharSequence bodyPeek, final ResponseBody body) throws IOException {
            final CustomBufferedInputStream bis = new CustomBufferedInputStream(
                    new GZIPInputStream(body.byteStream()));

            // initialize input stream
            final LittleEndianDataInputStream is = new LittleEndianDataInputStream(bis);
            is.mark(expectedBufferSize);

            // quick check of status
            final int version = is.readShortReverse();
            if (version != 6 && version != 5)
                throw new IllegalStateException("unknown version: " + version + ", first chars: " + bodyPeek);
            final ResultHeader header = new ResultHeader(network, SERVER_PRODUCT, Integer.toString(version),
                    null, 0, null);

            // quick seek for pointers
            is.reset();
            is.skipBytes(0x20);
            final int serviceDaysTablePtr = is.readIntReverse();
            final int stringTablePtr = is.readIntReverse();

            is.reset();
            is.skipBytes(0x36);
            final int stationTablePtr = is.readIntReverse();
            final int commentTablePtr = is.readIntReverse();

            is.reset();
            is.skipBytes(0x46);
            final int extensionHeaderPtr = is.readIntReverse();

            // read strings
            final StringTable strings = new StringTable(is, stringTablePtr,
                    serviceDaysTablePtr - stringTablePtr);

            is.reset();
            is.skipBytes(extensionHeaderPtr);

            // read extension header
            final int extensionHeaderLength = is.readIntReverse();
            if (extensionHeaderLength < 0x2c)
                throw new IllegalStateException("too short: " + extensionHeaderLength);

            is.skipBytes(12);
            final int errorCode = is.readShortReverse();

            if (errorCode == 0) {
                // string encoding
                is.skipBytes(14);
                final Charset stringEncoding = Charset.forName(strings.read(is));
                strings.setEncoding(stringEncoding);

                // read number of trips
                is.reset();
                is.skipBytes(30);

                final int numTrips = is.readShortReverse();
                if (numTrips == 0) {
                    result.set(new QueryTripsResult(header, url.toString(), from, via, to, null,
                            new LinkedList<Trip>()));
                    return;
                }

                // read rest of header
                is.reset();
                is.skipBytes(0x02);

                final Location resDeparture = location(is, strings);
                final Location resArrival = location(is, strings);

                is.skipBytes(10);

                final long resDate = date(is);
                /* final long resDate30 = */date(is);

                is.reset();
                is.skipBytes(extensionHeaderPtr + 0x8);

                final int seqNr = is.readShortReverse();
                if (seqNr == 0)
                    throw new SessionExpiredException();
                else if (seqNr < 0)
                    throw new IllegalStateException("illegal sequence number: " + seqNr);

                final String requestId = strings.read(is);

                final int tripDetailsPtr = is.readIntReverse();
                if (tripDetailsPtr == 0)
                    throw new IllegalStateException("no connection details");

                is.skipBytes(4);

                final int disruptionsPtr = is.readIntReverse();

                is.skipBytes(10);

                final String ld = strings.read(is);
                final int attrsOffset = is.readIntReverse();

                final int tripAttrsPtr;
                if (extensionHeaderLength >= 0x30) {
                    if (extensionHeaderLength < 0x32)
                        throw new IllegalArgumentException("too short: " + extensionHeaderLength);
                    is.reset();
                    is.skipBytes(extensionHeaderPtr + 0x2c);
                    tripAttrsPtr = is.readIntReverse();
                } else {
                    tripAttrsPtr = 0;
                }

                // determine stops offset
                is.reset();
                is.skipBytes(tripDetailsPtr);
                final int tripDetailsVersion = is.readShortReverse();
                if (tripDetailsVersion != 1)
                    throw new IllegalStateException("unknown trip details version: " + tripDetailsVersion);
                is.skipBytes(0x02);

                final int tripDetailsIndexOffset = is.readShortReverse();
                final int tripDetailsLegOffset = is.readShortReverse();
                final int tripDetailsLegSize = is.readShortReverse();
                final int stopsSize = is.readShortReverse();
                final int stopsOffset = is.readShortReverse();

                // read stations
                final StationTable stations = new StationTable(is, stationTablePtr,
                        commentTablePtr - stationTablePtr, strings);

                // read comments
                final CommentTable comments = new CommentTable(is, commentTablePtr,
                        tripDetailsPtr - commentTablePtr, strings);

                final List<Trip> trips = new ArrayList<>(numTrips);

                // read trips
                for (int iTrip = 0; iTrip < numTrips; iTrip++) {
                    is.reset();
                    is.skipBytes(0x4a + iTrip * 12);

                    final int serviceDaysTableOffset = is.readShortReverse();

                    final int legsOffset = is.readIntReverse();

                    final int numLegs = is.readShortReverse();

                    final int numChanges = is.readShortReverse();

                    /* final long duration = time(is, 0, 0); */is.readShortReverse();

                    is.reset();
                    is.skipBytes(serviceDaysTablePtr + serviceDaysTableOffset);

                    /* final String serviceDaysText = */strings.read(is);

                    final int serviceBitBase = is.readShortReverse();
                    final int serviceBitLength = is.readShortReverse();

                    int tripDayOffset = serviceBitBase * 8;
                    for (int i = 0; i < serviceBitLength; i++) {
                        int serviceBits = is.read();
                        if (serviceBits == 0) {
                            tripDayOffset += 8;
                            continue;
                        }
                        while ((serviceBits & 0x80) == 0) {
                            serviceBits = serviceBits << 1;
                            tripDayOffset++;
                        }
                        break;
                    }

                    is.reset();
                    is.skipBytes(tripDetailsPtr + tripDetailsIndexOffset + iTrip * 2);
                    final int tripDetailsOffset = is.readShortReverse();

                    is.reset();
                    is.skipBytes(tripDetailsPtr + tripDetailsOffset);
                    final int realtimeStatus = is.readShortReverse();

                    /* final short delay = */is.readShortReverse();

                    /* final int legIndex = */is.readShortReverse();

                    is.skipBytes(2); // 0xffff

                    /* final int legStatus = */is.readShortReverse();

                    is.skipBytes(2); // 0x0000

                    String connectionId = null;
                    if (tripAttrsPtr != 0) {
                        is.reset();
                        is.skipBytes(tripAttrsPtr + iTrip * 2);
                        final int tripAttrsIndex = is.readShortReverse();

                        is.reset();
                        is.skipBytes(attrsOffset + tripAttrsIndex * 4);
                        while (true) {
                            final String key = strings.read(is);
                            if (key == null)
                                break;
                            else if (key.equals("ConnectionId"))
                                connectionId = strings.read(is);
                            else
                                is.skipBytes(2);
                        }
                    }

                    final List<Trip.Leg> legs = new ArrayList<>(numLegs);

                    for (int iLegs = 0; iLegs < numLegs; iLegs++) {
                        is.reset();
                        is.skipBytes(0x4a + legsOffset + iLegs * 20);

                        final long plannedDepartureTime = time(is, resDate, tripDayOffset);
                        final Location departureLocation = stations.read(is);

                        final long plannedArrivalTime = time(is, resDate, tripDayOffset);
                        final Location arrivalLocation = stations.read(is);

                        final int type = is.readShortReverse();

                        final String lineName = strings.read(is);

                        final Position plannedDeparturePosition = normalizePosition(strings.read(is));
                        final Position plannedArrivalPosition = normalizePosition(strings.read(is));

                        final int legAttrIndex = is.readShortReverse();

                        final List<Line.Attr> lineAttrs = new ArrayList<>();
                        String lineComment = null;
                        boolean lineOnDemand = false;
                        for (final String comment : comments.read(is)) {
                            if (comment.startsWith("bf ")) {
                                lineAttrs.add(Line.Attr.WHEEL_CHAIR_ACCESS);
                            } else if (comment.startsWith("FA ") || comment.startsWith("FB ")
                                    || comment.startsWith("FR ")) {
                                lineAttrs.add(Line.Attr.BICYCLE_CARRIAGE);
                            } else if (comment.startsWith("$R ") || comment.startsWith("ga ")
                                    || comment.startsWith("ja ") || comment.startsWith("Vs ")
                                    || comment.startsWith("mu ") || comment.startsWith("mx ")) {
                                lineOnDemand = true;
                                lineComment = comment.substring(5);
                            }
                        }

                        is.reset();
                        is.skipBytes(attrsOffset + legAttrIndex * 4);
                        String directionStr = null;
                        int lineClass = 0;
                        String lineCategory = null;
                        String routingType = null;
                        String lineNetwork = null;
                        while (true) {
                            final String key = strings.read(is);
                            if (key == null)
                                break;
                            else if (key.equals("Direction"))
                                directionStr = strings.read(is);
                            else if (key.equals("Class"))
                                lineClass = Integer.parseInt(strings.read(is));
                            else if (key.equals("Category"))
                                lineCategory = strings.read(is);
                            // else if (key.equals("Operator"))
                            // lineOperator = strings.read(is);
                            else if (key.equals("GisRoutingType"))
                                routingType = strings.read(is);
                            else if (key.equals("AdminCode"))
                                lineNetwork = normalizeLineAdministration(strings.read(is));
                            else
                                is.skipBytes(2);
                        }

                        if (lineCategory == null && lineName != null)
                            lineCategory = categoryFromName(lineName);

                        is.reset();
                        is.skipBytes(tripDetailsPtr + tripDetailsOffset + tripDetailsLegOffset
                                + iLegs * tripDetailsLegSize);

                        if (tripDetailsLegSize != 16)
                            throw new IllegalStateException(
                                    "unhandled trip details leg size: " + tripDetailsLegSize);

                        final long predictedDepartureTime = time(is, resDate, tripDayOffset);
                        final long predictedArrivalTime = time(is, resDate, tripDayOffset);
                        final Position predictedDeparturePosition = normalizePosition(strings.read(is));
                        final Position predictedArrivalPosition = normalizePosition(strings.read(is));

                        final int bits = is.readShortReverse();
                        final boolean arrivalCancelled = (bits & 0x10) != 0;
                        final boolean departureCancelled = (bits & 0x20) != 0;

                        is.readShort();

                        final int firstStopIndex = is.readShortReverse();

                        final int numStops = is.readShortReverse();

                        is.reset();
                        is.skipBytes(disruptionsPtr);

                        String disruptionText = null;

                        if (is.readShortReverse() == 1) {
                            is.reset();
                            is.skipBytes(disruptionsPtr + 2 + iTrip * 2);

                            int disruptionsOffset = is.readShortReverse();
                            while (disruptionsOffset != 0) {
                                is.reset();
                                is.skipBytes(disruptionsPtr + disruptionsOffset);

                                strings.read(is); // "0"

                                final int disruptionLeg = is.readShortReverse();

                                is.skipBytes(2); // bitmaske

                                strings.read(is); // start of line
                                strings.read(is); // end of line

                                strings.read(is);
                                // id
                                /* final String disruptionTitle = */strings.read(is);
                                final String disruptionShortText = ParserUtils.formatHtml(strings.read(is));

                                disruptionsOffset = is.readShortReverse(); // next

                                if (iLegs == disruptionLeg) {
                                    final int disruptionAttrsIndex = is.readShortReverse();

                                    is.reset();
                                    is.skipBytes(attrsOffset + disruptionAttrsIndex * 4);

                                    while (true) {
                                        final String key = strings.read(is);
                                        if (key == null)
                                            break;
                                        else if (key.equals("Text"))
                                            disruptionText = ParserUtils.resolveEntities(strings.read(is));
                                        else
                                            is.skipBytes(2);
                                    }

                                    if (disruptionShortText != null)
                                        disruptionText = disruptionShortText;
                                }
                            }
                        }

                        List<Stop> intermediateStops = null;

                        if (numStops > 0) {
                            is.reset();
                            is.skipBytes(tripDetailsPtr + stopsOffset + firstStopIndex * stopsSize);

                            if (stopsSize != 26)
                                throw new IllegalStateException("unhandled stops size: " + stopsSize);

                            intermediateStops = new ArrayList<>(numStops);

                            for (int iStop = 0; iStop < numStops; iStop++) {
                                final long plannedStopDepartureTime = time(is, resDate, tripDayOffset);
                                final Date plannedStopDepartureDate = plannedStopDepartureTime != 0
                                        ? new Date(plannedStopDepartureTime)
                                        : null;
                                final long plannedStopArrivalTime = time(is, resDate, tripDayOffset);
                                final Date plannedStopArrivalDate = plannedStopArrivalTime != 0
                                        ? new Date(plannedStopArrivalTime)
                                        : null;
                                final Position plannedStopDeparturePosition = normalizePosition(
                                        strings.read(is));
                                final Position plannedStopArrivalPosition = normalizePosition(strings.read(is));

                                is.readInt();

                                final long predictedStopDepartureTime = time(is, resDate, tripDayOffset);
                                final Date predictedStopDepartureDate = predictedStopDepartureTime != 0
                                        ? new Date(predictedStopDepartureTime)
                                        : null;
                                final long predictedStopArrivalTime = time(is, resDate, tripDayOffset);
                                final Date predictedStopArrivalDate = predictedStopArrivalTime != 0
                                        ? new Date(predictedStopArrivalTime)
                                        : null;
                                final Position predictedStopDeparturePosition = normalizePosition(
                                        strings.read(is));
                                final Position predictedStopArrivalPosition = normalizePosition(
                                        strings.read(is));

                                final int stopBits = is.readShortReverse();
                                final boolean stopArrivalCancelled = (stopBits & 0x10) != 0;
                                final boolean stopDepartureCancelled = (stopBits & 0x20) != 0;

                                is.readShort();

                                final Location stopLocation = stations.read(is);

                                final boolean validPredictedDate = !dominantPlanStopTime
                                        || (plannedStopArrivalDate != null && plannedStopDepartureDate != null);

                                final Stop stop = new Stop(stopLocation, plannedStopArrivalDate,
                                        validPredictedDate ? predictedStopArrivalDate : null,
                                        plannedStopArrivalPosition, predictedStopArrivalPosition,
                                        stopArrivalCancelled, plannedStopDepartureDate,
                                        validPredictedDate ? predictedStopDepartureDate : null,
                                        plannedStopDeparturePosition, predictedStopDeparturePosition,
                                        stopDepartureCancelled);

                                intermediateStops.add(stop);
                            }
                        }

                        final Trip.Leg leg;
                        if (type == 1 /* Fussweg */ || type == 3 /* Uebergang */ || type == 4 /* Uebergang */) {
                            final Trip.Individual.Type individualType;
                            if (routingType == null)
                                individualType = type == 1 ? Trip.Individual.Type.WALK
                                        : Trip.Individual.Type.TRANSFER;
                            else if ("FOOT".equals(routingType))
                                individualType = Trip.Individual.Type.WALK;
                            else if ("BIKE".equals(routingType))
                                individualType = Trip.Individual.Type.BIKE;
                            else if ("CAR".equals(routingType) || "P+R".equals(routingType))
                                individualType = Trip.Individual.Type.CAR;
                            else
                                throw new IllegalStateException("unknown routingType: " + routingType);

                            final Date departureTime = new Date(
                                    predictedDepartureTime != 0 ? predictedDepartureTime
                                            : plannedDepartureTime);
                            final Date arrivalTime = new Date(
                                    predictedArrivalTime != 0 ? predictedArrivalTime : plannedArrivalTime);

                            final Trip.Leg lastLeg = legs.size() > 0 ? legs.get(legs.size() - 1) : null;
                            if (lastLeg != null && lastLeg instanceof Trip.Individual
                                    && ((Trip.Individual) lastLeg).type == individualType) {
                                final Trip.Individual lastIndividualLeg = (Trip.Individual) legs
                                        .remove(legs.size() - 1);
                                leg = new Trip.Individual(individualType, lastIndividualLeg.departure,
                                        lastIndividualLeg.departureTime, arrivalLocation, arrivalTime, null, 0);
                            } else {
                                leg = new Trip.Individual(individualType, departureLocation, departureTime,
                                        arrivalLocation, arrivalTime, null, 0);
                            }
                        } else if (type == 2) {
                            final Product lineProduct;
                            if (lineOnDemand)
                                lineProduct = Product.ON_DEMAND;
                            else if (lineClass != 0)
                                lineProduct = intToProduct(lineClass);
                            else
                                lineProduct = normalizeType(lineCategory);

                            final Line line = newLine(lineNetwork, lineProduct, normalizeLineName(lineName),
                                    lineComment, lineAttrs.toArray(new Line.Attr[0]));

                            final Location direction;
                            if (directionStr != null) {
                                final String[] directionPlaceAndName = splitStationName(directionStr);
                                direction = new Location(LocationType.ANY, null, directionPlaceAndName[0],
                                        directionPlaceAndName[1]);
                            } else {
                                direction = null;
                            }

                            final Stop departure = new Stop(departureLocation, true,
                                    plannedDepartureTime != 0 ? new Date(plannedDepartureTime) : null,
                                    predictedDepartureTime != 0 ? new Date(predictedDepartureTime) : null,
                                    plannedDeparturePosition, predictedDeparturePosition, departureCancelled);
                            final Stop arrival = new Stop(arrivalLocation, false,
                                    plannedArrivalTime != 0 ? new Date(plannedArrivalTime) : null,
                                    predictedArrivalTime != 0 ? new Date(predictedArrivalTime) : null,
                                    plannedArrivalPosition, predictedArrivalPosition, arrivalCancelled);

                            leg = new Trip.Public(line, direction, departure, arrival, intermediateStops, null,
                                    disruptionText);
                        } else {
                            throw new IllegalStateException("unhandled type: " + type);
                        }
                        legs.add(leg);
                    }

                    final Trip trip = new Trip(connectionId, resDeparture, resArrival, legs, null, null,
                            (int) numChanges);

                    if (realtimeStatus != 2) // Verbindung fllt aus
                        trips.add(trip);
                }

                // if result is only one single individual leg, don't query for more
                final boolean canQueryMore = trips.size() != 1 || trips.get(0).legs.size() != 1
                        || !(trips.get(0).legs.get(0) instanceof Trip.Individual);

                result.set(new QueryTripsResult(header, url.toString(), from, via, to,
                        new QueryTripsBinaryContext(requestId, seqNr, ld, bis.getCount(), canQueryMore),
                        trips));
            } else {
                log.debug("Hafas error: {}", errorCode);
                if (errorCode == 1) {
                    throw new SessionExpiredException();
                } else if (errorCode == 2) {
                    // F2: Your search results could not be stored internally.
                    throw new SessionExpiredException();
                } else if (errorCode == 8) {
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.AMBIGUOUS));
                    return;
                } else if (errorCode == 13) {
                    // IN13: Our booking system is currently being used by too many users at the same
                    // time.
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.SERVICE_DOWN));
                    return;
                } else if (errorCode == 19) {
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.SERVICE_DOWN));
                    return;
                } else if (errorCode == 207) {
                    // H207: Unfortunately your connection request can currently not be processed.
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.SERVICE_DOWN));
                    return;
                } else if (errorCode == 887) {
                    // H887: Your inquiry was too complex. Please try entering less intermediate stations.
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.NO_TRIPS));
                    return;
                } else if (errorCode == 890) {
                    // H890: No connections have been found that correspond to your request. It is
                    // possible
                    // that the requested service does not operate from or to the places you stated on the
                    // requested date of travel.
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.NO_TRIPS));
                    return;
                } else if (errorCode == 891) {
                    // H891: Unfortunately there was no route found. Missing timetable data could be the
                    // reason.
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.NO_TRIPS));
                    return;
                } else if (errorCode == 892) {
                    // H892: Your inquiry was too complex. Please try entering less intermediate stations.
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.NO_TRIPS));
                    return;
                } else if (errorCode == 899) {
                    // H899: there was an unsuccessful or incomplete search due to a timetable change.
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.NO_TRIPS));
                    return;
                } else if (errorCode == 900) {
                    // Unsuccessful or incomplete search (timetable change)
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.NO_TRIPS));
                    return;
                } else if (errorCode == 9220) {
                    // H9220: Nearby to the given address stations could not be found.
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.UNRESOLVABLE_ADDRESS));
                    return;
                } else if (errorCode == 9240) {
                    // H9240: Unfortunately there was no route found. Perhaps your start or destination is
                    // not
                    // served at all or with the selected means of transport on the required date/time.
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.NO_TRIPS));
                    return;
                } else if (errorCode == 9260) {
                    // H9260: Unknown departure station
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.UNKNOWN_FROM));
                    return;
                } else if (errorCode == 9280) {
                    // H9280: Unknown intermediate station
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.UNKNOWN_VIA));
                    return;
                } else if (errorCode == 9300) {
                    // H9300: Unknown arrival station
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.UNKNOWN_TO));
                    return;
                } else if (errorCode == 9320) {
                    // The input is incorrect or incomplete
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.INVALID_DATE));
                    return;
                } else if (errorCode == 9360) {
                    // H9360: Unfortunately your connection request can currently not be processed.
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.INVALID_DATE));
                    return;
                } else if (errorCode == 9380) {
                    // H9380: Dep./Arr./Intermed. or equivalent station defined more than once
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.TOO_CLOSE));
                    return;
                } else if (errorCode == 895) {
                    // H895: Departure/Arrival are too near
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.TOO_CLOSE));
                    return;
                } else if (errorCode == 65535) {
                    result.set(new QueryTripsResult(header, QueryTripsResult.Status.SERVICE_DOWN));
                    return;
                } else {
                    throw new IllegalStateException("error " + errorCode + " on " + url);
                }
            }
        }
    }, url);

    return result.get();
}