List of usage examples for java.util.concurrent.atomic AtomicReference set
public final void set(V newValue)
From source file:org.geotools.jdbc.JoiningJDBCFeatureSource.java
/** * Generates a 'SELECT p1, p2, ... FROM ... WHERE ...' prepared statement. * /*w w w. j a v a 2 s. co m*/ * @param featureType * the feature type that the query must return (may contain less attributes than the * native one) * @param attributes * the properties queried, or {@link Query#ALL_NAMES} to gather all of them * @param query * the query to be run. The type name and property will be ignored, as they are * supposed to have been already embedded into the provided feature type * @param cx * The database connection to be used to create the prepared statement * @throws SQLException * @throws IOException * @throws FilterToSQLException */ protected String selectSQL(SimpleFeatureType featureType, JoiningQuery query, AtomicReference<PreparedFilterToSQL> toSQLref) throws IOException, SQLException, FilterToSQLException { // first we create from clause, for aliases StringBuffer fromclause = new StringBuffer(); getDataStore().encodeTableName(featureType.getTypeName(), fromclause, query.getHints()); //joining Set<String> tableNames = new HashSet<String>(); String lastTypeName = featureType.getTypeName(); String curTypeName = lastTypeName; String[] aliases = null; if (query.getQueryJoins() != null) { aliases = new String[query.getQueryJoins().size()]; for (int i = 0; i < query.getQueryJoins().size(); i++) { JoiningQuery.QueryJoin join = query.getQueryJoins().get(i); fromclause.append(" INNER JOIN "); String alias = null; FilterToSQL toSQL1 = createFilterToSQL(getDataStore().getSchema(lastTypeName)); FilterToSQL toSQL2 = createFilterToSQL(getDataStore().getSchema(join.getJoiningTypeName())); String last_alias = createAlias(lastTypeName, tableNames); tableNames.add(last_alias); curTypeName = last_alias; if (tableNames.contains(join.getJoiningTypeName())) { alias = createAlias(join.getJoiningTypeName(), tableNames); aliases[i] = alias; getDataStore().encodeTableName(join.getJoiningTypeName(), fromclause, query.getHints()); fromclause.append(" "); getDataStore().dialect.encodeTableName(alias, fromclause); fromclause.append(" ON ( "); toSQL2.setFieldEncoder(new JoiningFieldEncoder(alias)); fromclause.append(toSQL2.encodeToString(join.getForeignKeyName())); } else { aliases[i] = null; getDataStore().encodeTableName(join.getJoiningTypeName(), fromclause, query.getHints()); fromclause.append(" ON ( "); toSQL2.setFieldEncoder(new JoiningFieldEncoder(join.getJoiningTypeName())); fromclause.append(toSQL2.encodeToString(join.getForeignKeyName())); } fromclause.append(" = "); toSQL1.setFieldEncoder(new JoiningFieldEncoder(curTypeName)); fromclause.append(toSQL1.encodeToString(join.getJoiningKeyName())); fromclause.append(") "); lastTypeName = join.getJoiningTypeName(); curTypeName = alias == null ? lastTypeName : alias; } } //begin sql StringBuffer sql = new StringBuffer(); sql.append("SELECT "); // primary key PrimaryKey key = null; try { key = getDataStore().getPrimaryKey(featureType); } catch (IOException e) { throw new RuntimeException(e); } Set<String> pkColumnNames = new HashSet<String>(); String colName; for (PrimaryKeyColumn col : key.getColumns()) { colName = col.getName(); encodeColumnName(colName, featureType.getTypeName(), sql, query.getHints()); sql.append(","); pkColumnNames.add(colName); } //other columns for (AttributeDescriptor att : featureType.getAttributeDescriptors()) { // skip the eventually exposed pk column values String columnName = att.getLocalName(); if (pkColumnNames.contains(columnName)) continue; if (att instanceof GeometryDescriptor) { //encode as geometry encodeGeometryColumn((GeometryDescriptor) att, featureType.getTypeName(), sql, query.getHints()); //alias it to be the name of the original geometry getDataStore().dialect.encodeColumnAlias(columnName, sql); } else { encodeColumnName(columnName, featureType.getTypeName(), sql, query.getHints()); } sql.append(","); } if (query.getQueryJoins() != null && query.getQueryJoins().size() > 0) { for (int i = 0; i < query.getQueryJoins().size(); i++) { for (int j = 0; j < query.getQueryJoins().get(i).getSortBy().length; j++) { if (aliases[i] != null) { getDataStore().dialect.encodeColumnName(aliases[i], query.getQueryJoins().get(i).getSortBy()[j].getPropertyName().getPropertyName(), sql); } else { encodeColumnName( query.getQueryJoins().get(i).getSortBy()[j].getPropertyName().getPropertyName(), query.getQueryJoins().get(i).getJoiningTypeName(), sql, query.getHints()); } sql.append(" ").append(FOREIGN_ID + "_" + i + "_" + j).append(","); } } } sql.setLength(sql.length() - 1); sql.append(" FROM "); sql.append(fromclause); //filtering FilterToSQL toSQL = null; Filter filter = query.getFilter(); if (filter != null && !Filter.INCLUDE.equals(filter)) { //encode filter try { SortBy[] lastSortBy = null; // leave it as null if it's asking for a subset, since we don't want to join to get // other rows of same id // since we don't want a full feature, but a subset only if (!query.isSubset()) { // grab the full feature type, as we might be encoding a filter // that uses attributes that aren't returned in the results lastSortBy = query.getQueryJoins() == null || query.getQueryJoins().size() == 0 ? query.getSortBy() : query.getQueryJoins().get(query.getQueryJoins().size() - 1).getSortBy(); } String lastTableName = query.getQueryJoins() == null || query.getQueryJoins().size() == 0 ? query.getTypeName() : query.getQueryJoins().get(query.getQueryJoins().size() - 1).getJoiningTypeName(); String lastTableAlias = query.getQueryJoins() == null || query.getQueryJoins().size() == 0 ? query.getTypeName() : aliases[query.getQueryJoins().size() - 1] == null ? lastTableName : aliases[query.getQueryJoins().size() - 1]; toSQL = createFilterToSQL(getDataStore().getSchema(lastTableName)); if (lastSortBy != null) { //we will use another join for the filter //assuming that the last sort by specifies the ID of the parent feature //this way we will ensure that if the table is denormalized, that all rows //with the same ID are included (for multi-valued features) sql.append(" INNER JOIN ( SELECT DISTINCT "); for (int i = 0; i < lastSortBy.length; i++) { getDataStore().dialect.encodeColumnName(null, lastSortBy[i].getPropertyName().getPropertyName(), sql); if (i < lastSortBy.length - 1) sql.append(","); } sql.append(" FROM "); getDataStore().encodeTableName(lastTableName, sql, query.getHints()); sql.append(" ").append(toSQL.encodeToString(filter)); sql.append(" ) " + TEMP_FILTER_ALIAS); sql.append(" ON ( "); for (int i = 0; i < lastSortBy.length; i++) { encodeColumnName2(lastSortBy[i].getPropertyName().getPropertyName(), lastTableAlias, sql, null); sql.append(" = "); encodeColumnName2(lastSortBy[i].getPropertyName().getPropertyName(), TEMP_FILTER_ALIAS, sql, null); if (i < lastSortBy.length - 1) sql.append(" AND "); } sql.append(" ) "); } else { toSQL.setFieldEncoder(new JoiningFieldEncoder(curTypeName)); sql.append(" ").append(toSQL.encodeToString(filter)); } } catch (FilterToSQLException e) { throw new RuntimeException(e); } } //sorting sort(query, sql, aliases, pkColumnNames); // finally encode limit/offset, if necessary getDataStore().applyLimitOffset(sql, query); if (toSQLref != null && toSQL instanceof PreparedFilterToSQL) { toSQLref.set((PreparedFilterToSQL) toSQL); } return sql.toString(); }
From source file:io.warp10.continuum.egress.EgressFetchHandler.java
private void packedDump(PrintWriter pw, GTSDecoderIterator iter, long now, long timespan, boolean dedup, boolean signed, AtomicReference<Metadata> lastMeta, AtomicLong lastCount, int maxDecoderLen, String classSuffix, long chunksize, boolean sortMeta) throws IOException { String name = null;//from w w w. ja v a 2 s . co m Map<String, String> labels = null; StringBuilder sb = new StringBuilder(); Metadata lastMetadata = lastMeta.get(); long currentCount = lastCount.get(); List<GTSEncoder> encoders = new ArrayList<GTSEncoder>(); while (iter.hasNext()) { GTSDecoder decoder = iter.next(); if (dedup) { decoder = decoder.dedup(); } if (!decoder.next()) { continue; } long toDecodeCount = Long.MAX_VALUE; if (timespan < 0) { Metadata meta = decoder.getMetadata(); if (!meta.equals(lastMetadata)) { lastMetadata = meta; currentCount = 0; } toDecodeCount = Math.max(0, -timespan - currentCount); } GTSEncoder encoder = decoder.getEncoder(true); // // Only display the class + labels if they have changed since the previous GTS // Map<String, String> lbls = decoder.getLabels(); // // Compute the name // name = decoder.getName(); labels = lbls; sb.setLength(0); GTSHelper.encodeName(sb, name + classSuffix); sb.append("{"); boolean first = true; if (sortMeta) { lbls = new TreeMap<String, String>(lbls); } for (Entry<String, String> entry : lbls.entrySet()) { // // Skip owner/producer labels and any other 'private' labels // if (!signed) { if (Constants.PRODUCER_LABEL.equals(entry.getKey())) { continue; } if (Constants.OWNER_LABEL.equals(entry.getKey())) { continue; } } if (!first) { sb.append(","); } GTSHelper.encodeName(sb, entry.getKey()); sb.append("="); GTSHelper.encodeName(sb, entry.getValue()); first = false; } sb.append("}"); // We treat the case where encoder.getCount() is 0 in a special way // as this may be because the encoder was generated from a partly // consumed decoder and thus its count was reset to 0 if (0 == encoder.getCount() || encoder.getCount() > toDecodeCount) { // We have too much data, shrink the encoder GTSEncoder enc = new GTSEncoder(); enc.safeSetMetadata(decoder.getMetadata()); while (decoder.next() && toDecodeCount > 0) { enc.addValue(decoder.getTimestamp(), decoder.getLocation(), decoder.getElevation(), decoder.getValue()); toDecodeCount--; } encoder = enc; } if (timespan < 0) { currentCount += encoder.getCount(); } encoders.clear(); // // Add encoders per chunk // GTSDecoder chunkdec = encoder.getDecoder(true); GTSEncoder chunkenc = null; Long lastchunk = null; if (Long.MAX_VALUE == chunksize) { encoders.add(encoder); } else { while (chunkdec.next()) { long ts = chunkdec.getTimestamp(); long chunk = ts >= 0 ? ts / chunksize : ((ts + 1) / chunksize) - 1; // // If it is the first chunk or we changed chunk, create a new encoder // if (null == chunkenc || (null != lastchunk && chunk != lastchunk)) { chunkenc = new GTSEncoder(0L); chunkenc.setMetadata(encoder.getMetadata()); encoders.add(chunkenc); } lastchunk = chunk; chunkenc.addValue(ts, chunkdec.getLocation(), chunkdec.getElevation(), chunkdec.getValue()); } } while (!encoders.isEmpty()) { encoder = encoders.remove(0); if (encoder.size() > 0) { // // Determine most recent timestamp // GTSDecoder dec = encoder.getDecoder(true); dec.next(); long timestamp = dec.getTimestamp(); // // Build GTSWrapper // encoder.setMetadata(new Metadata()); // Clear labels encoder.setName(""); encoder.setLabels(new HashMap<String, String>()); encoder.getMetadata().setAttributes(new HashMap<String, String>()); GTSWrapper wrapper = GTSWrapperHelper.fromGTSEncoderToGTSWrapper(encoder, true); TSerializer ser = new TSerializer(new TCompactProtocol.Factory()); byte[] serialized; try { serialized = ser.serialize(wrapper); } catch (TException te) { throw new IOException(te); } // // Check the size of the generatd wrapper. If it is over 75% of maxDecoderLen, // split the original encoder in two // if (serialized.length >= Math.floor(0.75D * maxDecoderLen) && encoder.getCount() > 2) { GTSEncoder split = new GTSEncoder(0L); split.setMetadata(encoder.getMetadata()); List<GTSEncoder> splits = new ArrayList<GTSEncoder>(); splits.add(split); int threshold = encoder.size() / 2; GTSDecoder deco = encoder.getDecoder(true); while (deco.next()) { split.addValue(deco.getTimestamp(), deco.getLocation(), deco.getElevation(), deco.getValue()); if (split.size() > threshold) { split = new GTSEncoder(0L); splits.add(split); } } // // Now insert the splits at the beginning of 'encoders' // for (int i = splits.size() - 1; i >= 0; i--) { encoders.add(0, splits.get(i)); } continue; } if (serialized.length > Math.ceil(0.75D * maxDecoderLen)) { throw new IOException( "Encountered a value whose length is above the configured threshold of " + maxDecoderLen); } pw.print(timestamp); pw.print("//"); pw.print(encoder.getCount()); pw.print(" "); pw.print(sb.toString()); pw.print(" '"); OrderPreservingBase64.encodeToWriter(serialized, pw); pw.print("'"); pw.write('\r'); pw.write('\n'); } } } lastMeta.set(lastMetadata); lastCount.set(currentCount); }
From source file:com.microsoft.tfs.core.clients.versioncontrol.internal.localworkspace.LocalDataAccessLayer.java
/** * * * * @param workspace/*from w w w . j a v a2s . c om*/ * @param lv * @param pc * @param changeRequests * @param silent * @param failures * @return */ public static GetOperation[] pendAdd(final Workspace workspace, final LocalWorkspaceProperties wp, final WorkspaceVersionTable lv, final LocalPendingChangesTable pc, final ChangeRequest[] changeRequests, final boolean silent, final AtomicReference<Failure[]> failures, final String[] itemPropertyFilters) { Check.notNull(workspace, "workspace"); //$NON-NLS-1$ Check.notNullOrEmpty(changeRequests, "changeRequests"); //$NON-NLS-1$ final List<Failure> failureList = new ArrayList<Failure>(); final List<GetOperation> getOps = new ArrayList<GetOperation>(); // Most duplicates filters are by WorkspaceLocalItem instance; but since // we are creating local version entries ourselves, we have to filter by // target server item. final Set<String> duplicatesFilter = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); for (final ChangeRequest changeRequest : changeRequests) { if (null == changeRequest) { continue; } // It is not legal to modify the state of a lock through a local // call. Check.isTrue( changeRequest.getLockLevel() == LockLevel.UNCHANGED || changeRequest.getLockLevel() == LockLevel.NONE, "changeRequest.getLockLevel() == LockLevel.UNCHANGED || changeRequest.getLockLevel() == LockLevel.NONE"); //$NON-NLS-1$ // The paths for PendAdd must be local items with no recursion. if (ServerPath.isServerPath(changeRequest.getItemSpec().getItem()) || RecursionType.NONE != changeRequest.getItemSpec().getRecursionType()) { throw new IllegalArgumentException(MessageFormat.format( Messages.getString("LocalDataAccessLayer.ChangeRequestMustBeLocalNonRecursiveFormat"), //$NON-NLS-1$ changeRequest.getItemSpec())); } LocalPath.checkLocalItem(changeRequest.getItemSpec().getItem(), "item", false, false, false, true); //$NON-NLS-1$ // The local item includes all pending renames of parents so we // treat it as a target server item. final String targetServerItem = WorkingFolder .getServerItemForLocalItem(changeRequest.getItemSpec().getItem(), wp.getWorkingFolders()); if (null == targetServerItem) { // We should have already validated that the path is mapped; so // if the server item is null, the item must be cloaked. failureList.add(createItemCloakedFailure(changeRequest.getItemSpec().getItem())); continue; } // Verify the length of the resultant target server item meets our // constraints. if (targetServerItem.length() > VersionControlConstants.MAX_SERVER_PATH_SIZE) { failureList.add(createPathTooLongFailure(targetServerItem)); continue; } WorkspaceLocalItem lvEntry = lv.getByLocalItem(changeRequest.getItemSpec().getItem()); LocalPendingChange pcEntry = pc.getByTargetServerItem(targetServerItem); final Failure teamProjectValidationFailure = TeamProject.validateChange(targetServerItem, changeRequest.getItemType()); // if we have a committed local version row, fall back to the error // below. if (teamProjectValidationFailure != null && (lvEntry == null || lvEntry.getVersion() == 0)) { failureList.add(teamProjectValidationFailure); continue; } else if (pcEntry != null && pcEntry.isAdd()) { // Existing pending add. Skip other validators and re-use the // existing pending change. // No change will be made to the existing pending change -- for // example the encoding will *not* be changed to respect the // encoding supplied on this ChangeRequest. } else if (pcEntry != null) { failureList .add(new Failure( MessageFormat.format( Messages.getString( "LocalDataAccessLayer.ChangeAlreadyPendingExceptionFormat"), //$NON-NLS-1$ targetServerItem), FailureCodes.CHANGE_ALREADY_PENDING_EXCEPTION, SeverityType.ERROR, changeRequest.getItemSpec().getItem())); continue; } else if (lvEntry != null && lvEntry.getVersion() != 0) { failureList.add(new Failure( MessageFormat.format(Messages.getString("LocalDataAccessLayer.ItemExistsExceptionFormat"), //$NON-NLS-1$ targetServerItem), FailureCodes.ITEM_EXISTS_EXCEPTION, SeverityType.ERROR, changeRequest.getItemSpec().getItem())); continue; } else if (pc.getRecursiveChangeTypeForTargetServerItem(targetServerItem).contains(ChangeType.DELETE)) { final String changedItem = changeRequest.getItemSpec().getItem(); failureList.add(createPendingParentDeleteFailure(targetServerItem, changedItem)); continue; } if (null == lvEntry) { lvEntry = new WorkspaceLocalItem(); lvEntry.setServerItem(targetServerItem); lvEntry.setVersion(0); lvEntry.setLocalItem(changeRequest.getItemSpec().getItem()); lvEntry.setEncoding((ItemType.FILE == changeRequest.getItemType()) ? changeRequest.getEncoding() : VersionControlConstants.ENCODING_FOLDER); lvEntry.setPendingReconcile(true); lv.add(lvEntry); } lvEntry.setPropertyValues(changeRequest.getProperties()); if (null == pcEntry) { pcEntry = new LocalPendingChange(lvEntry, targetServerItem, ChangeType.ADD_ENCODING); pcEntry.setEncoding(lvEntry.getEncoding()); pcEntry.setTargetServerItem(targetServerItem); pcEntry.setCommittedServerItem(null); if (ItemType.FILE == changeRequest.getItemType()) { pcEntry.setChangeType(pcEntry.getChangeType().combine(ChangeType.EDIT)); } if (changeRequest.getProperties() != null && changeRequest.getProperties().length > 0) { pcEntry.setChangeType(pcEntry.getChangeType().combine(ChangeType.PROPERTY)); pcEntry.setPropertyValues(changeRequest.getProperties()); } pc.pendChange(pcEntry); pc.removeCandidateByTargetServerItem(targetServerItem); } // Create the GetOperation for this pending change. if (!silent) { if (!duplicatesFilter.add(lvEntry.getServerItem())) { continue; } getOps.add(lvEntry.toGetOperation(pcEntry, itemPropertyFilters)); } } for (final Failure failure : failureList) { failure.setRequestType(RequestType.ADD); } failures.set(failureList.toArray(new Failure[failureList.size()])); return getOps.toArray(new GetOperation[getOps.size()]); }
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 www. j a v 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
/** * Pend these changes for this workspace on the server. * * @param requests//from ww w . j a va 2s . 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:io.warp10.continuum.egress.EgressFetchHandler.java
/** * Output a tab separated version of fetched data. Deduplication is done on the fly so we don't decode twice. * /* w w w .jav a 2 s .com*/ */ private static void tsvDump(PrintWriter pw, GTSDecoderIterator iter, long now, long timespan, boolean raw, boolean dedup, boolean signed, AtomicReference<Metadata> lastMeta, AtomicLong lastCount, boolean sortMeta) throws IOException { String name = null; Map<String, String> labels = null; StringBuilder classSB = new StringBuilder(); StringBuilder labelsSB = new StringBuilder(); StringBuilder attributesSB = new StringBuilder(); StringBuilder valueSB = new StringBuilder(); Metadata lastMetadata = lastMeta.get(); long currentCount = lastCount.get(); while (iter.hasNext()) { GTSDecoder decoder = iter.next(); if (!decoder.next()) { continue; } long toDecodeCount = Long.MAX_VALUE; if (timespan < 0) { Metadata meta = decoder.getMetadata(); if (!meta.equals(lastMetadata)) { lastMetadata = meta; currentCount = 0; } toDecodeCount = Math.max(0, -timespan - currentCount); } // // Only display the class + labels if they have changed since the previous GTS // Map<String, String> lbls = decoder.getLabels(); // // Compute the new name // boolean displayName = false; if (null == name || (!name.equals(decoder.getName()) || !labels.equals(lbls))) { displayName = true; name = decoder.getName(); labels = lbls; classSB.setLength(0); GTSHelper.encodeName(classSB, name); labelsSB.setLength(0); attributesSB.setLength(0); boolean first = true; if (sortMeta) { lbls = new TreeMap<String, String>(lbls); } for (Entry<String, String> entry : lbls.entrySet()) { // // Skip owner/producer labels and any other 'private' labels // if (!signed) { if (Constants.PRODUCER_LABEL.equals(entry.getKey())) { continue; } if (Constants.OWNER_LABEL.equals(entry.getKey())) { continue; } } if (!first) { labelsSB.append(","); } GTSHelper.encodeName(labelsSB, entry.getKey()); labelsSB.append("="); GTSHelper.encodeName(labelsSB, entry.getValue()); first = false; } first = true; if (decoder.getMetadata().getAttributesSize() > 0) { if (sortMeta) { decoder.getMetadata() .setAttributes(new TreeMap<String, String>(decoder.getMetadata().getAttributes())); } for (Entry<String, String> entry : decoder.getMetadata().getAttributes().entrySet()) { if (!first) { attributesSB.append(","); } GTSHelper.encodeName(attributesSB, entry.getKey()); attributesSB.append("="); GTSHelper.encodeName(attributesSB, entry.getValue()); first = false; } } } long timestamp = 0L; long location = GeoTimeSerie.NO_LOCATION; long elevation = GeoTimeSerie.NO_ELEVATION; Object value = null; boolean dup = true; long decoded = 0; do { if (toDecodeCount == decoded) { break; } // // Filter out any value not in the time range // long newTimestamp = decoder.getTimestamp(); if (newTimestamp > now || (timespan >= 0 && newTimestamp <= (now - timespan))) { continue; } // // TODO(hbs): filter out values with no location or outside the selected geozone when a geozone was set // long newLocation = decoder.getLocation(); long newElevation = decoder.getElevation(); Object newValue = decoder.getValue(); dup = true; if (dedup) { if (location != newLocation || elevation != newElevation) { dup = false; } else { if (null == newValue) { // Consider nulls as duplicates (can't happen!) dup = false; } else if (newValue instanceof Number) { if (!((Number) newValue).equals(value)) { dup = false; } } else if (newValue instanceof String) { if (!((String) newValue).equals(value)) { dup = false; } } else if (newValue instanceof Boolean) { if (!((Boolean) newValue).equals(value)) { dup = false; } } } } decoded++; location = newLocation; elevation = newElevation; timestamp = newTimestamp; value = newValue; if (raw) { if (!dedup || !dup) { pw.print(classSB); pw.print('\t'); pw.print(labelsSB); pw.print('\t'); pw.print(attributesSB); pw.print('\t'); pw.print(timestamp); pw.print('\t'); if (GeoTimeSerie.NO_LOCATION != location) { double[] latlon = GeoXPLib.fromGeoXPPoint(location); pw.print(latlon[0]); pw.print('\t'); pw.print(latlon[1]); } else { pw.print('\t'); } pw.print('\t'); if (GeoTimeSerie.NO_ELEVATION != elevation) { pw.print(elevation); } pw.print('\t'); valueSB.setLength(0); GTSHelper.encodeValue(valueSB, value); pw.println(valueSB); } } else { // Display the name only if we have at least one value to display // We force 'dup' to be false when we must show the name if (displayName) { pw.print("# "); pw.print(classSB); pw.print("{"); pw.print(labelsSB); pw.print("}"); pw.print("{"); pw.print(attributesSB); pw.println("}"); displayName = false; dup = false; } if (!dedup || !dup) { pw.print(timestamp); pw.print('\t'); if (GeoTimeSerie.NO_LOCATION != location) { double[] latlon = GeoXPLib.fromGeoXPPoint(location); pw.print(latlon[0]); pw.print('\t'); pw.print(latlon[1]); } else { pw.print('\t'); } pw.print('\t'); if (GeoTimeSerie.NO_ELEVATION != elevation) { pw.print(elevation); } pw.print('\t'); valueSB.setLength(0); GTSHelper.encodeValue(valueSB, value); pw.println(valueSB); } } } while (decoder.next()); // Update currentcount if (timespan < 0) { currentCount += decoded; } // Print any remaining value if (dedup && dup) { if (raw) { pw.print(classSB); pw.print('\t'); pw.print(labelsSB); pw.print('\t'); pw.print(attributesSB); pw.print('\t'); pw.print(timestamp); pw.print('\t'); if (GeoTimeSerie.NO_LOCATION != location) { double[] latlon = GeoXPLib.fromGeoXPPoint(location); pw.print(latlon[0]); pw.print('\t'); pw.print(latlon[1]); } else { pw.print('\t'); } pw.print('\t'); if (GeoTimeSerie.NO_ELEVATION != elevation) { pw.print(elevation); } pw.print('\t'); valueSB.setLength(0); GTSHelper.encodeValue(valueSB, value); pw.println(valueSB); } else { pw.print(timestamp); pw.print('\t'); if (GeoTimeSerie.NO_LOCATION != location) { double[] latlon = GeoXPLib.fromGeoXPPoint(location); pw.print(latlon[0]); pw.print('\t'); pw.print(latlon[1]); } else { pw.print('\t'); } pw.print('\t'); if (GeoTimeSerie.NO_ELEVATION != elevation) { pw.print(elevation); } pw.print('\t'); valueSB.setLength(0); GTSHelper.encodeValue(valueSB, value); pw.println(valueSB); } } // // If displayName is still true it means we should have displayed the name but no value matched, // so set name to null so we correctly display the name for the next decoder if it has values // if (displayName) { name = null; } } lastMeta.set(lastMetadata); lastCount.set(currentCount); }
From source file:com.microsoft.tfs.core.clients.versioncontrol.internal.localworkspace.LocalDataAccessLayer.java
/** * * * * @param workspace//from ww w .j a v a 2s . c o m * @param lv * @param pc * @param changeRequests * @param silent * @param failures * @return */ public static GetOperation[] pendDelete(final Workspace workspace, final LocalWorkspaceProperties wp, final WorkspaceVersionTable lv, final LocalPendingChangesTable pc, final ChangeRequest[] changeRequests, final boolean silent, final AtomicReference<Failure[]> failures, final String[] itemPropertyFilters) { Check.notNull(workspace, "workspace"); //$NON-NLS-1$ Check.notNullOrEmpty(changeRequests, "changeRequests"); //$NON-NLS-1$ workspace.getWorkspaceWatcher().scan(wp, lv, pc); final List<Failure> failureList = new ArrayList<Failure>(); final List<GetOperation> getOps = new ArrayList<GetOperation>(); final Set<WorkspaceLocalItem> duplicatesFilter = new HashSet<WorkspaceLocalItem>(); for (final ChangeRequest changeRequest : changeRequests) { if (null == changeRequest) { continue; } // It is not legal to modify the state of a lock through a local // call. Check.isTrue(changeRequest.getLockLevel() == LockLevel.UNCHANGED, "changeRequest.getLockLevel() == LockLevel.UNCHANGED"); //$NON-NLS-1$ if (ServerPath.isRootFolder(changeRequest.getItemSpec().getItem())) { failureList.add(new Failure(Messages.getString("TeamProject.CanNotChangeRootFolderException"), //$NON-NLS-1$ FailureCodes.CANNOT_CHANGE_ROOT_FOLDER_EXCEPTION, SeverityType.ERROR, changeRequest.getItemSpec().getItem())); continue; } final ParsedItemSpec parsedItemSpec = ParsedItemSpec.fromItemSpec(changeRequest.getItemSpec(), wp, lv, pc, ParsedItemSpecOptions.INCLUDE_DELETED, failureList); if (null == parsedItemSpec) { continue; } // Check up front to see if the item provided is deleted. Emit the // appropriate errors if so. final String rootTargetServerItem; if (parsedItemSpec.isServerItem()) { rootTargetServerItem = parsedItemSpec.getTargetItem(); } else { rootTargetServerItem = WorkingFolder.getServerItemForLocalItem(parsedItemSpec.getTargetItem(), wp.getWorkingFolders()); } if (null != rootTargetServerItem) { if (rootTargetServerItem.length() > VersionControlConstants.MAX_SERVER_PATH_SIZE) { failureList.add(createPathTooLongFailure(rootTargetServerItem)); continue; } final LocalPendingChange pcEntry = pc.getByTargetServerItem(rootTargetServerItem); if (null != pcEntry && pcEntry.isDelete()) { failureList.add(createPendingDeleteConflictChangeFailure(rootTargetServerItem)); continue; } else if (pc.getRecursiveChangeTypeForTargetServerItem(rootTargetServerItem) .contains(ChangeType.DELETE)) { failureList.add(createPendingParentDeleteFailure(rootTargetServerItem)); continue; } } for (final WorkspaceLocalItem lvEntry : parsedItemSpec.expandRootsFrom(lv, pc, failureList)) { if (!duplicatesFilter.add(lvEntry)) { continue; } final String targetServerItem = pc.getTargetServerItemForLocalVersion(lvEntry); final Failure failure = TeamProject.validateChange(targetServerItem, changeRequest.getItemType()); if (failure != null) { failureList.add(failure); continue; } LocalPendingChange pcEntry = pc.getByLocalVersion(lvEntry); // Permit the lock, property and branch bits. If the branch bit // is specified, permit the encoding and merge bits, too. // Additionally permit PendDelete to stomp on pending edits if // the item is missing from disk. if (null != pcEntry) { ChangeType remainingChangeType = pcEntry.getChangeType().remove(ChangeType.LOCK) .remove(ChangeType.BRANCH).remove(ChangeType.PROPERTY); if (pcEntry.isBranch()) { remainingChangeType = remainingChangeType.remove(ChangeType.ENCODING) .remove(ChangeType.MERGE); } if (pcEntry.isEdit() && lvEntry.isMissingOnDisk()) { remainingChangeType = remainingChangeType.remove(ChangeType.EDIT); } if (!remainingChangeType.equals(ChangeType.NONE)) { failureList.add(createPendingDeleteConflictChangeFailure(targetServerItem)); continue; } } if (lvEntry.isDirectory()) { boolean okayToDelete = true; for (final LocalPendingChange pcChildEntry : pc.queryByTargetServerItem(targetServerItem, RecursionType.FULL, null)) { if (pcChildEntry.getChangeType().containsAny(PEND_DELETE_CONFLICTING_CHANGE_TYPES)) { failureList.add(createPendingDeleteConflictChangeFailure(targetServerItem)); okayToDelete = false; break; } } if (!okayToDelete) { continue; } for (final LocalPendingChange pcRenamedOut : pc .queryByCommittedServerItem(lvEntry.getServerItem(), RecursionType.FULL, null)) { if (pcRenamedOut.isRename()) { final String format = Messages .getString("LocalDataAccessLayer.PendingChildExceptionFormat"); //$NON-NLS-1$ failureList.add(new Failure(MessageFormat.format(format, targetServerItem), FailureCodes.PENDING_CHILD_EXCEPTION, SeverityType.ERROR, targetServerItem)); okayToDelete = false; break; } } if (!okayToDelete) { continue; } } if (pc.getRecursiveChangeTypeForTargetServerItem(targetServerItem).contains(ChangeType.DELETE)) { failureList.add(createPendingParentDeleteFailure(targetServerItem)); continue; } if (null == pcEntry) { pcEntry = new LocalPendingChange(lvEntry, targetServerItem, ChangeType.DELETE); } else { pcEntry.setChangeType(pcEntry.getChangeType().combine(ChangeType.DELETE)); // It's possible to pend a delete on an item whose local // version entry is marked as MissingFromDisk. In this case, // we want to strip the edit bit -- it's not a pending edit // any longer. pcEntry.setChangeType(pcEntry.getChangeType().remove(ChangeType.EDIT)); } pc.pendChange(pcEntry); pc.removeCandidateByTargetServerItem(targetServerItem, true); if (lvEntry.isDirectory()) { final List<String> childDeletesToRemove = new ArrayList<String>(); for (final LocalPendingChange pcChildEntry : pc.queryByTargetServerItem(targetServerItem, RecursionType.FULL, "*")) //$NON-NLS-1$ { if (pcChildEntry.getChangeType().equals(ChangeType.DELETE)) { childDeletesToRemove.add(pcChildEntry.getTargetServerItem()); } else { pcChildEntry.setChangeType(pcChildEntry.getChangeType().combine(ChangeType.DELETE)); } } for (final String toRemove : childDeletesToRemove) { pc.removeByTargetServerItem(toRemove); } } // Generate GetOperations for this pending change. if (!silent) { final GetOperation rootGetOp = lvEntry.toGetOperation(pcEntry, itemPropertyFilters); rootGetOp.setTargetLocalItem(null); getOps.add(rootGetOp); if (lvEntry.isDirectory()) { final Iterable<WorkspaceLocalItem> lvChildEntries = lv .queryByServerItem(lvEntry.getServerItem(), RecursionType.FULL, "*"); //$NON-NLS-1$ for (final WorkspaceLocalItem lvChildEntry : lvChildEntries) { if (!duplicatesFilter.add(lvChildEntry)) { continue; } final GetOperation childGetOp = lvChildEntry.toGetOperation(itemPropertyFilters); childGetOp.setBaselineFileGUID(null); childGetOp.setTargetLocalItem(null); childGetOp.setPendingChangeID(0); childGetOp.setChangeType(pc.getRecursiveChangeTypeForLocalVersion(lvChildEntry)); childGetOp.setProcessType(ProcessType.PEND); getOps.add(childGetOp); } } } } } for (final Failure failure : failureList) { failure.setRequestType(RequestType.DELETE); } failures.set(failureList.toArray(new Failure[failureList.size()])); return getOps.toArray(new GetOperation[getOps.size()]); }
From source file:com.microsoft.tfs.core.clients.versioncontrol.soapextensions.Workspace.java
/** * Update the given items for the given workspace. * <p>/*from w w w. j a v a 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 requests * the request items to process (must not be null; items in array * must not be null). To update all items in this workspace, pass a * single {@link GetRequest} with a null itemSpec. * @param options * options for the get operation (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>) * @param alwaysQueryConflicts * true to always query conflicts, false if we may omit this step * @param conflicts * a reference to a list of conflicts to return (must not be * <code>null</code>) * @return a GetStatus instance with the results of the get operation. */ public GetStatus get(final GetRequest[] requests, final GetOptions options, String[] itemPropertyFilters, final boolean alwaysQueryConflicts, final AtomicReference<Conflict[]> conflicts) { Check.notNull(requests, "requests"); //$NON-NLS-1$ Check.notNull(options, "options"); //$NON-NLS-1$ Check.notNull(conflicts, "conflicts"); //$NON-NLS-1$ // Using web service directly so merge filters configured on client itemPropertyFilters = client.mergeWithDefaultItemPropertyFilters(itemPropertyFilters); client.getEventEngine() .fireOperationStarted(new GetOperationStartedEvent(EventSource.newFromHere(), this, requests)); /* * Always work toward 100 work units. The progress indicator will only * be accurate for gets that fit in one page (result set). If we have to * process more than one set we'll fill up the task monitor prematurely, * which is not an error. Pages are huge so almost all requests will fit * inside one. */ final TaskMonitor taskMonitor = TaskMonitorService.getTaskMonitor(); taskMonitor.begin("", 100); //$NON-NLS-1$ taskMonitor.setCurrentWorkDescription( Messages.getString("Workspace.ContactingServertoGetListOfItemsToUpdate")); //$NON-NLS-1$ /* * Specify a limit to number of Get operation results that server may * return from a single call. This is to guard against client running * out of memory, and also to guard against Http runtime timeout on * server when streaming a large result set back to the client. This * "paging" technique relies on the page advancing once we process the * results from the previous call. This is incompatible with force * option. */ final boolean getAll = options.contains(GetOptions.GET_ALL); final int maxResults = getAll ? 0 : VersionControlConstants.MAX_GET_RESULTS; final GetStatus getStatus = new GetStatus(); try { String[] sourceWritableConflicts; final WritableConflictOnSourcePathListener conflictListener = new WritableConflictOnSourcePathListener(); try { client.getEventEngine().addGetListener(conflictListener); GetStatus latestStatus = null; final GetEngine getEngine = new GetEngine(client); int resultCount; /* * Call the server. If we specify a page limit, call repeatedly * as long as we keep getting a full page back. * * Paging like this makes progress monitoring hard, because we * don't know the total amount of work up front. */ do { log.debug("Call server for GetOperations."); //$NON-NLS-1$ final GetOperation[][] results = client.getWebServiceLayer().get(getName(), getOwnerName(), requests, maxResults, options, null, itemPropertyFilters, false); // Web service call always gets 5 taskMonitor.worked(5); // How many results were returned? Is it a full page (see // loop // terminating condition)? resultCount = 0; for (final GetOperation[] result : results) { resultCount += result.length; } log.debug("Process GetOperations"); //$NON-NLS-1$ // Use 95 for the processing. TaskMonitorService.pushTaskMonitor(taskMonitor.newSubTaskMonitor(95)); try { latestStatus = getEngine.processGetOperations(this, ProcessType.GET, RequestType.NONE, results, options, false, true, ChangePendedFlags.UNKNOWN); } catch (final Exception e) { log.error("Error processing GET operations", e); //$NON-NLS-1$ if (e instanceof VersionControlException) { throw (VersionControlException) e; } else { throw new VersionControlException(e); } } finally { TaskMonitorService.popTaskMonitor(true); } log.debug("Latest GetOperations status:"); //$NON-NLS-1$ log.debug(" NumOperations = " + latestStatus.getNumOperations()); //$NON-NLS-1$ log.debug(" NumUpdated = " + latestStatus.getNumUpdated()); //$NON-NLS-1$ log.debug(" NumWarnings = " + latestStatus.getNumWarnings()); //$NON-NLS-1$ log.debug(" NumFailures = " + latestStatus.getNumFailures()); //$NON-NLS-1$ log.debug(" NumConflicts = " + latestStatus.getNumConflicts()); //$NON-NLS-1$ log.debug(" NumResolvedConflicts = " + latestStatus.getNumResolvedConflicts()); //$NON-NLS-1$ getStatus.combine(latestStatus); } while (VersionControlConstants.MAX_GET_RESULTS > 0 && resultCount == VersionControlConstants.MAX_GET_RESULTS && latestStatus.getNumUpdated() >= 1); sourceWritableConflicts = conflictListener.getMovedPaths(); } finally { client.getEventEngine().removeGetListener(conflictListener); } final boolean attemptAutoResolve = (!options.contains(GetOptions.NO_AUTO_RESOLVE)); if (getStatus.getNumConflicts() > 0 || getStatus.haveResolvableWarnings() && (alwaysQueryConflicts || attemptAutoResolve)) { log.debug("Querying conflicts."); //$NON-NLS-1$ taskMonitor.setCurrentWorkDescription(Messages.getString("Workspace.QueryingConflicts")); //$NON-NLS-1$ final AtomicBoolean recursive = new AtomicBoolean(); final String[] conflictScope = calculateConflictScope(requests, sourceWritableConflicts, recursive); Conflict[] unresolvedConflicts = queryConflicts(conflictScope, recursive.get()); if (attemptAutoResolve) { log.debug("Resolving conflicts."); //$NON-NLS-1$ taskMonitor.setCurrentWorkDescription(Messages.getString("Workspace.ResolvingConflicts")); //$NON-NLS-1$ /* Auto resolve the conflicts */ unresolvedConflicts = client.autoResolveValidConflicts(this, unresolvedConflicts, AutoResolveOptions.ALL_SILENT); /* * Update the get status information about conflicts. We * don't change the value of HaveResolvableWarnings because * we won't auto resolve local conflicts. */ getStatus.setNumConflicts(unresolvedConflicts.length); } log.debug("Unresolved conflicts: " + unresolvedConflicts.length); //$NON-NLS-1$ conflicts.set(unresolvedConflicts); } } finally { /* * Event handlers may run a while but not update the work * description, so set a generic message so the user knows things * are wrapping up. */ taskMonitor.setCurrentWorkDescription(Messages.getString("Workspace.FinishingGetOperation")); //$NON-NLS-1$ client.getEventEngine().fireOperationCompleted( new GetOperationCompletedEvent(EventSource.newFromHere(), this, requests, getStatus)); Workstation.getCurrent(getClient().getConnection().getPersistenceStoreProvider()) .notifyForWorkspace(this, Notification.VERSION_CONTROL_GET_COMPLETED); taskMonitor.done(); } return getStatus; }
From source file:com.microsoft.tfs.core.clients.versioncontrol.internal.localworkspace.LocalDataAccessLayer.java
public static GetOperation[] undoPendingChanges(final Workspace workspace, final LocalWorkspaceProperties wp, final WorkspaceVersionTable lv, final LocalPendingChangesTable pc, final Iterable<LocalPendingChange> pendingChanges, final ChangeType selectiveUndo, final AtomicReference<Failure[]> failures, final AtomicBoolean onlineOperationRequired) { // Our collection of GetOperations that we will return. There will be // one GetOperation for every undone pending change and for every item // affected by an undone recursive pending change. The dictionary is // keyed by (SourceServerItem, IsCommitted) just like the local version // table.//from ww w . j ava 2 s .c o m final Map<ServerItemIsCommittedTuple, GetOperation> getOps = new HashMap<ServerItemIsCommittedTuple, GetOperation>(); // The UndoneChange structure encapsulates a pending change and its // destination server item in pending space (RevertToServerItem). final List<UndoneChange> undoneChanges = new ArrayList<UndoneChange>(); // A hash table where we can check quickly to see if a server path has a // pending change being undone (by target server item) final Map<String, UndoneChange> undoneChangesMap = new HashMap<String, UndoneChange>(); // When a recursive pending change is undone, there may be affected // child pending changes that are not undone. We store in this queue a // list of updates that need to be processed (atomically!). final List<RenamedPendingChange> renamedPendingChanges = new ArrayList<RenamedPendingChange>(); // When undoing a rename, we need to make sure that the current target // server item isn't at or below a workspace mapping. List<String> workingFolderServerItems = null; // Failures generated by undo final List<Failure> failureList = new ArrayList<Failure>(); int undoRenameCount = 0; // The RevertToServerItem starts out with the CommittedServerItem of the // pending change. for (final LocalPendingChange pcEntry : pendingChanges) { final ChangeType changeType = pcEntry.getChangeType().retain(selectiveUndo); final UndoneChange undoneChange = new UndoneChange(pcEntry, pcEntry.getServerItem(), changeType); // Add this item to our data structures undoneChanges.add(undoneChange); undoneChangesMap.put(undoneChange.getPendingChange().getTargetServerItem(), undoneChange); // We can't undo a checkin lock without going to the server. If we // match one, the entire undo operation needs to go to the server. if (undoneChange.isUndoingLock() || (undoneChange.isUndoingRename() && undoneChange.getPendingChange().isLock())) { return sendToServer(failures, onlineOperationRequired); } // Count how many renames we are undoing and make sure the rename is // not at or under a workspace mapping if (undoneChange.isUndoingRename()) { undoRenameCount++; // The first rename will initialize our list of working folders // and sort it if (null == workingFolderServerItems) { final WorkingFolder[] workingFolders = wp.getWorkingFolders(); workingFolderServerItems = new ArrayList<String>(workingFolders.length); for (final WorkingFolder workingFolder : workingFolders) { workingFolderServerItems.add(workingFolder.getServerItem()); } Collections.sort(workingFolderServerItems, new Comparator<String>() { @Override public int compare(final String x, final String y) { return ServerPath.compareTopDown(x, y); } }); } // Check to see if undoing this rename would modify the // workspace mappings final int index = Collections.binarySearch(workingFolderServerItems, pcEntry.getTargetServerItem(), ServerPath.TOP_DOWN_COMPARATOR); if (index >= 0 || (~index < workingFolderServerItems.size() && ServerPath .isChild(pcEntry.getTargetServerItem(), workingFolderServerItems.get(~index)))) { return sendToServer(failures, onlineOperationRequired); } } } // Sort by target server item descending Collections.sort(undoneChanges, new Comparator<UndoneChange>() { @Override public int compare(final UndoneChange x, final UndoneChange y) { return ServerPath.compareTopDown(y.getPendingChange().getTargetServerItem(), x.getPendingChange().getTargetServerItem()); } }); // Pass 1: Calculate the RevertToServerItem for each undone pending // change. if (undoRenameCount > 0) { // We should come up with a faster way of figuring out whether the // user is undoing all renames in the workspace. int totalRenameCount = 0; final List<LocalPendingChange> remainingFolderRenames = new ArrayList<LocalPendingChange>(); for (final LocalPendingChange pcEntry : pc.queryByTargetServerItem(ServerPath.ROOT, RecursionType.FULL, null)) { if (pcEntry.isRename()) { totalRenameCount++; if (pcEntry.isRecursiveChange()) { final UndoneChange undoneChange = undoneChangesMap.get(pcEntry.getTargetServerItem()); if (undoneChange == null || !undoneChange.isUndoingRename()) { remainingFolderRenames.add(pcEntry); } } } } if (undoneChanges.size() != pc.getCount()) { // We are not undoing all the changes in the workspace, so we // need to make sure that we do not have any pending changes // that are not being undone that have a target server item that // is at or underneath the source of a pending rename. Otherwise // there will be a collision when we undo the rename and it goes // back to the source. for (final UndoneChange undoneChange : undoneChanges) { final LocalPendingChange lpc = undoneChange.getPendingChange(); // TODO: What kinds of bad situations can we end up with // when you have a merge of a deleted item under a rename -- // a pending merge on a deleted item if (0 == lpc.getDeletionID() && lpc.isCommitted() && undoneChange.isUndoingRename() && !ServerPath.equals(lpc.getCommittedServerItem(), lpc.getTargetServerItem())) { // Check to see if there is a namespace-additive pending // change blocking this item from reverting to its // committed server item for (final LocalPendingChange pcEntry : pc.queryByTargetServerItem( undoneChange.getPendingChange().getCommittedServerItem(), RecursionType.FULL, null)) { if (pcEntry.isAdd() || pcEntry.isBranch() || pcEntry.isRename()) { final UndoneChange collision = undoneChangesMap.get(pcEntry.getTargetServerItem()); if (collision == null || !collision.getUndoneChangeType() .containsAny(ChangeType.ADD_BRANCH_OR_RENAME)) { final String format = Messages .getString("LocalDataAccessLayer.PartialRenameConflictExceptionFormat"); //$NON-NLS-1$ throw new PartialRenameConflictException( MessageFormat.format(format, pcEntry.getTargetServerItem())); } } } } } } if (undoRenameCount != totalRenameCount) { // Only some of the renames in the workspace are being undone // Find a pending folder rename (PARENT\a->PARENT\b) that is // NOT being undone which is affecting a pending folder rename // (PARENT\A\SUB -> OUTSIDE) that IS being undone Where the // depth of the target name for the rename being undone // (OUTSIDE) is less than the depth of the target name that is // NOT being undone (PARENT\B). for (final LocalPendingChange remainingFolderRename : remainingFolderRenames) { for (final LocalPendingChange pcEntry : pc.queryByCommittedServerItem( remainingFolderRename.getCommittedServerItem(), RecursionType.FULL, null)) { if (pcEntry.isRename() && pcEntry.isRecursiveChange()) { final UndoneChange undoneChange = undoneChangesMap.get(pcEntry.getTargetServerItem()); final int targetFolderDepth = ServerPath.getFolderDepth(pcEntry.getTargetServerItem()); final int remainFolderDepth = ServerPath .getFolderDepth(remainingFolderRename.getTargetServerItem()); if (undoneChange != null && undoneChange.isUndoingRename() && targetFolderDepth < remainFolderDepth) { final String format = Messages .getString("LocalDataAccessLayer.PartialRenameConflictExceptionFormat"); //$NON-NLS-1$ throw new PartialRenameConflictException( MessageFormat.format(format, pcEntry.getCommittedServerItem())); } } } } // Calculate new names for all namespace-changing pending // changes. // Map of key server item (current target server item) to the // data structure used for the name calculation. We'll use this // later to sub in the new names. final Map<String, RenameCalculationEntry> newNames = new HashMap<String, RenameCalculationEntry>(); // Our algorithm wants to walk the set of pending renames only. final List<RenameCalculationEntry> pendingRenamesOnly = new ArrayList<RenameCalculationEntry>( totalRenameCount); for (final UndoneChange undoneChange : undoneChanges) { final RenameCalculationEntry rcEntry = new RenameCalculationEntry( undoneChange.getPendingChange().getTargetServerItem(), undoneChange.getPendingChange().getServerItem(), undoneChange.getPendingChange(), undoneChange.isUndoingRename()); newNames.put(undoneChange.getPendingChange().getTargetServerItem(), rcEntry); if (undoneChange.getPendingChange().isRename()) { pendingRenamesOnly.add(rcEntry); } } for (final LocalPendingChange pcEntry : pc.queryByTargetServerItem(ServerPath.ROOT, RecursionType.FULL, null)) { if ((pcEntry.isRename() || pcEntry.isAdd() || pcEntry.isBranch()) && !undoneChangesMap.containsKey(pcEntry.getTargetServerItem())) { final RenameCalculationEntry rcEntry = new RenameCalculationEntry( pcEntry.getTargetServerItem(), pcEntry.getServerItem(), pcEntry, false); newNames.put(pcEntry.getTargetServerItem(), rcEntry); if (pcEntry.isRename()) { pendingRenamesOnly.add(rcEntry); } } } // Our algorithm wants to walk the set of pending renames only, // by source server item ascending. Collections.sort(pendingRenamesOnly, new Comparator<RenameCalculationEntry>() { @Override public int compare(final RenameCalculationEntry x, final RenameCalculationEntry y) { return ServerPath.compareTopDown(x.getPendingChange().getCommittedServerItem(), y.getPendingChange().getCommittedServerItem()); } }); for (final RenameCalculationEntry newName : pendingRenamesOnly) { // Capture the data from newName into local variables, since // we will be checking/editing values on the very same // instance of RenameCalculationEntry in our up coming // for each loops final String sourceServerItem = newName.getSourceServerItem(); final String targetServerItem = newName.getTargetServerItem(); if (!newName.isUndoingChange()) { for (final RenameCalculationEntry rcEntry : newNames.values()) { final String entrySourceServerItem = rcEntry.getSourceServerItem(); if (ServerPath.isChild(sourceServerItem, entrySourceServerItem)) { final String entryTargetServerItem = rcEntry.getTargetServerItem(); final String pendingTargetServerItem = rcEntry.getPendingChange() .getTargetServerItem(); if (!ServerPath.equals(entrySourceServerItem, entryTargetServerItem) || ServerPath.equals(pendingTargetServerItem, entrySourceServerItem)) { rcEntry.setSourceServerItem(targetServerItem + entrySourceServerItem.substring(sourceServerItem.length())); } } } } else { for (final RenameCalculationEntry rcEntry : newNames.values()) { final String entryTargetServerItem = rcEntry.getTargetServerItem(); if (ServerPath.isChild(targetServerItem, entryTargetServerItem)) { final String entrySourceServerItem = rcEntry.getSourceServerItem(); final String pendingTargetServerItem = rcEntry.getPendingChange() .getTargetServerItem(); if (!ServerPath.equals(entrySourceServerItem, entryTargetServerItem) || ServerPath.equals(pendingTargetServerItem, entrySourceServerItem)) { rcEntry.setTargetServerItem(sourceServerItem + entryTargetServerItem.substring(targetServerItem.length())); } } } } } // If there are duplicate TargetServerItem values in the set of // RenameCalculationEntry objects, that indicates we have a // collision and cannot perform the undo. Sort by target server // item so that duplicates will be adjacent. final RenameCalculationEntry[] rcEntries = newNames.values() .toArray(new RenameCalculationEntry[newNames.size()]); Arrays.sort(rcEntries, new Comparator<RenameCalculationEntry>() { @Override public int compare(final RenameCalculationEntry x, final RenameCalculationEntry y) { return ServerPath.compareTopDown(x.getTargetServerItem(), y.getTargetServerItem()); } }); // The loop is complicated because we need to exclude pending // renames on deleted items from consideration. int duplicateCheckIndex = -1; for (int i = 1; i < rcEntries.length; i++) { // Only allow rcEntries[duplicateCheckIndex] to point to a // pending change which meets our criteria if (rcEntries[i - 1].getPendingChange().getDeletionID() == 0 || !rcEntries[i - 1].getPendingChange().isRename()) { duplicateCheckIndex = i - 1; } // This pending change must also meet the criteria, we must // have something to compare it against, and the target // server items need to be the same. if (duplicateCheckIndex >= 0 && (rcEntries[i].getPendingChange().getDeletionID() == 0 || !rcEntries[i].getPendingChange().isRename()) && ServerPath.equals(rcEntries[i].getTargetServerItem(), rcEntries[duplicateCheckIndex].getTargetServerItem())) { throw new PartialRenameConflictException(MessageFormat.format( Messages.getString("LocalDataAccessLayer.PartialRenameConflictExceptionFormat"), //$NON-NLS-1$ , rcEntries[i].getTargetServerItem())); } } for (final UndoneChange undoneChange : undoneChanges) { final RenameCalculationEntry rcEntry = newNames .get(undoneChange.getPendingChange().getTargetServerItem()); if (rcEntry != null) { undoneChange.setRevertToServerItem(rcEntry.getTargetServerItem()); } } } else { // All renames in the workspace are being undone. for (final UndoneChange undoneChange : undoneChanges) { if (undoneChange.getPendingChange().isCommitted()) { // Committed changes have their revert to server item // already calculated. undoneChange .setRevertToServerItem(undoneChange.getPendingChange().getCommittedServerItem()); } else { // Find the closest rename that affects this uncommitted // item and unrename it. undoneChange.setRevertToServerItem(pc.getCommittedServerItemForTargetServerItem( undoneChange.getPendingChange().getTargetServerItem())); } } } } else { // Even though we are not undoing a rename, there could be a // parental rename. So set the revert to server item based upon // existing parental renames. for (final UndoneChange undoneChange : undoneChanges) { undoneChange.setRevertToServerItem(undoneChange.getPendingChange().getTargetServerItem()); } } // Pass 1: One GetOperation for every LocalPendingChange being undone for (final UndoneChange undoneChange : undoneChanges) { if (undoneChange.getRevertToServerItem().length() > VersionControlConstants.MAX_SERVER_PATH_SIZE) { throw createPathTooLongException(undoneChange.getRevertToServerItem()); } final LocalPendingChange pcEntry = undoneChange.getPendingChange(); final WorkspaceLocalItem lvEntry = lv.getByPendingChange(undoneChange.getPendingChange()); final GetOperation getOp = new GetOperation(); getOp.setTargetServerItem(undoneChange.getRevertToServerItem()); getOp.setSourceServerItem( pcEntry.isCommitted() ? pcEntry.getCommittedServerItem() : pcEntry.getTargetServerItem()); if (null != lvEntry && !lvEntry.isDeleted()) { getOp.setSourceLocalItem(lvEntry.getLocalItem()); // If we're undoing a pending add, mark the path as changed in // the scanner. This is because when the pending change is // undone, the item in question will not actually be touched on // disk. But we want to have it marked, so that we re-detect the // item as a candidate add. if (undoneChange.isUndoingAdd()) { workspace.getWorkspaceWatcher().markPathChanged(lvEntry.getLocalItem()); LocalWorkspaceTransaction.getCurrent().setRaisePendingChangeCandidatesChanged(true); } } if ((0 == pcEntry.getDeletionID() || undoneChange.getRemainingChangeType().contains(ChangeType.UNDELETE)) && !undoneChange.isUndoingBranch()) { final String targetLocalItem = WorkingFolder .getLocalItemForServerItem(undoneChange.getRevertToServerItem(), wp.getWorkingFolders()); if (null != lvEntry) { getOp.setTargetLocalItem(targetLocalItem); // We never want the client to delete adds -- even if the // target is cloaked. if (pcEntry.isAdd() && null == getOp.getTargetLocalItem()) { getOp.setTargetLocalItem(getOp.getSourceLocalItem()); } } else { // We don't have a local version entry for this pending // change, so we can't restore the content. getOp.setTargetLocalItem(null); if (null != targetLocalItem) { final String format = "OfflineUndoNoLocalVersionEntry"; //$NON-NLS-1$ failureList .add(new Failure(MessageFormat.format(format, undoneChange.getRevertToServerItem()), FailureCodes.BASELINE_UNAVAILABLE_EXCEPTION, SeverityType.WARNING, undoneChange.getRevertToServerItem())); } } if (null != getOp.getTargetLocalItem()) { getOp.setLocalVersionEntry(lv.getByLocalItem(getOp.getTargetLocalItem())); } } // This is the current encoding on the pending change -- we need the // committed encoding, which is on the local version entry if we // have one, but if we don't, we're in trouble and need to go to the // server. if (!pcEntry.getChangeType().contains(ChangeType.ENCODING)) { // If we aren't changing the encoding, then the local pending // change row's encoding is the encoding for the item. getOp.setEncoding(pcEntry.getEncoding()); } else if (null != lvEntry) { getOp.setEncoding(lvEntry.getEncoding()); } else { // We don't have the committed encoding for this item stored // locally. We need to process this undo operation on the // server. // TODO: Issue a warning and not download the change? The user // can go to the server and get it later, we don't want to // completely block them while they're offline return sendToServer(failures, onlineOperationRequired); } getOp.setChangeType(undoneChange.getUndoneChangeType()); // If we are undoing an uncommitted pending change then do not add // in parent recursive changetypes if (!undoneChange.isUndoingAdd() && !undoneChange.isUndoingBranch()) { ChangeType inheritedChangeType = ChangeType.NONE; // The ChangeType on the item being undone is equal to the // ChangeType on the item itself, plus the recursive ChangeType // on its parent pending changes which are also being undone. for (final LocalPendingChange parentPcEntry : pc .queryParentsOfTargetServerItem(pcEntry.getTargetServerItem())) { final UndoneChange checkChange = undoneChangesMap.get(parentPcEntry.getTargetServerItem()); if (!parentPcEntry.isRecursiveChange() || checkChange == null) { continue; } if (checkChange.getUndoneChangeType().contains(ChangeType.RENAME)) { inheritedChangeType = inheritedChangeType.combine(ChangeType.RENAME); } if (checkChange.getUndoneChangeType().contains(ChangeType.DELETE)) { inheritedChangeType = inheritedChangeType.combine(ChangeType.DELETE); } } getOp.setChangeType(inheritedChangeType.combine(getOp.getChangeType())); } getOp.setDeletionID(pcEntry.getDeletionID()); getOp.setItemType(pcEntry.getItemType()); getOp.setPendingChangeID(LocalPendingChange.LOCAL_PENDING_CHANGE_ID); getOp.setItemID(pcEntry.getItemID()); if (null != lvEntry) { if (lvEntry.isCommitted() && !lvEntry.isDirectory()) { getOp.setBaselineFileGUID( lvEntry.hasBaselineFileGUID() ? lvEntry.getBaselineFileGUID() : new byte[16]); } getOp.setHashValue(lvEntry.getHashValue()); getOp.setVersionLocal(lvEntry.isDeleted() ? 0 : lvEntry.getVersion()); getOp.setVersionServer(lvEntry.getVersion()); getOp.setVersionServerDate((-1 == lvEntry.getCheckinDate()) ? DotNETDate.MIN_CALENDAR : DotNETDate.fromWindowsFileTimeUTC(lvEntry.getCheckinDate())); getOp.setPropertyValues(pcEntry.getPropertyValues()); } else { getOp.setVersionServer(pcEntry.getVersion()); } getOps.put(new ServerItemIsCommittedTuple(getOp.getSourceServerItem(), pcEntry.isCommitted()), getOp); // Remove local version rows for adds, branches where the item is an // add, or we are syncing an item on top of an undone branch. if (undoneChange.isUndoingAdd() || (undoneChange.isUndoingBranch() && getOp.getTargetLocalItem() != null)) { if (null != lvEntry) { lv.removeByServerItem(lvEntry.getServerItem(), lvEntry.isCommitted(), true); } } } // Pass 2: Affected items underneath undone recursive changes for (final UndoneChange undoneChange : undoneChanges) { if (!undoneChange.isUndoingRecursiveChange()) { continue; } // The sort order means that undoneChange is always the closest // recursive operation affecting the item for (final WorkspaceLocalItem lvEntry : ParsedItemSpec.queryLocalVersionsByTargetServerItem(lv, pc, undoneChange.getPendingChange().getTargetServerItem(), RecursionType.FULL, null, ParsedItemSpecOptions.INCLUDE_DELETED)) { if (getOps.containsKey( new ServerItemIsCommittedTuple(lvEntry.getServerItem(), lvEntry.isCommitted()))) { continue; } final String currentServerItem = lvEntry.isCommitted() ? pc.getTargetServerItemForCommittedServerItem(lvEntry.getServerItem()) : lvEntry.getServerItem(); final GetOperation getOp = new GetOperation(); getOp.setSourceLocalItem(lvEntry.isDeleted() ? null : lvEntry.getLocalItem()); getOp.setTargetServerItem(undoneChange.getRevertToServerItem() + currentServerItem .substring(undoneChange.getPendingChange().getTargetServerItem().length())); if (getOp.getTargetServerItem().length() > VersionControlConstants.MAX_SERVER_PATH_SIZE) { throw createPathTooLongException(getOp.getTargetServerItem()); } getOp.setSourceServerItem( lvEntry.isCommitted() ? lvEntry.getServerItem() : getOp.getTargetServerItem()); getOp.setTargetLocalItem(WorkingFolder.getLocalItemForServerItem(getOp.getTargetServerItem(), wp.getWorkingFolders())); if (null != getOp.getTargetLocalItem()) { getOp.setLocalVersionEntry(lv.getByLocalItem(getOp.getTargetLocalItem())); } getOp.setDeletionID(0); getOp.setEncoding(lvEntry.getEncoding()); getOp.setItemType(lvEntry.isDirectory() ? ItemType.FOLDER : ItemType.FILE); getOp.setPropertyValues(lvEntry.getPropertyValues()); // Even if this item has a pending change which is not being // undone -- we return 0 here getOp.setPendingChangeID(0); getOp.setItemID(lvEntry.getItemID()); if (!ServerPath.equals(currentServerItem, getOp.getTargetServerItem())) { if (!lvEntry.isCommitted() && !ServerPath.equals(currentServerItem, getOp.getTargetServerItem())) { // Uncommitted items have the itemid of the target // server item, and we're changing paths, so set the // item id to 0 because we have no idea what the item id // of the target server item is getOp.setItemID(0); } final LocalPendingChange pcEntry = pc.getByTargetServerItem(currentServerItem); if (null != pcEntry) { if (pcEntry.isLock()) { // We cannot change the path of an item with a // pending lock locally. return sendToServer(failures, onlineOperationRequired); } if (pcEntry.hasMergeConflict()) { throw new CannotRenameDueToChildConflictException( undoneChange.getPendingChange().getTargetServerItem(), pcEntry.getTargetServerItem()); } // Queue this pending change for a later update of its // target path and itemid (if it still exists after // removing those pending changes that are being undone) renamedPendingChanges .add(new RenamedPendingChange(currentServerItem, getOp.getTargetServerItem())); } } if (lvEntry.isCommitted() && !lvEntry.isDirectory()) { getOp.setBaselineFileGUID( lvEntry.hasBaselineFileGUID() ? lvEntry.getBaselineFileGUID() : new byte[16]); } getOp.setHashValue(lvEntry.getHashValue()); getOp.setVersionLocal(lvEntry.isDeleted() ? 0 : lvEntry.getVersion()); getOp.setVersionServer(lvEntry.getVersion()); getOp.setVersionServerDate((-1 == lvEntry.getCheckinDate()) ? DotNETDate.MIN_CALENDAR : DotNETDate.fromWindowsFileTimeUTC(lvEntry.getCheckinDate())); getOp.setChangeType(ChangeType.NONE); // We'll take a quick look at the parents of this target server // item to determine if the item is still deleted. On this same // pass, we'll compute the ChangeType of the GetOperation to // generate. Since there was no pending change being undone on // this item, the ChangeType is equal to the union of the // recursive changetype bits on parent pending changes which are // being undone. boolean stillDeleted = false; for (final LocalPendingChange parentPcEntry : pc .queryParentsOfTargetServerItem(currentServerItem)) { final UndoneChange checkChange = undoneChangesMap.get(parentPcEntry.getTargetServerItem()); if (checkChange == null) { if (parentPcEntry.isDelete()) { stillDeleted = true; // Who cares what the ChangeType on the GetOperation // is, if we're not going to emit it? break; } } else { ChangeType changeType = getOp.getChangeType(); changeType = changeType.combine(checkChange.getUndoneChangeType()); changeType = changeType.combine(ChangeType.RENAME_OR_DELETE); getOp.setChangeType(changeType); } } if (!lvEntry.isDeleted() || !stillDeleted) { if (null != getOp.getTargetLocalItem() || null != getOp.getSourceLocalItem()) { getOps.put(new ServerItemIsCommittedTuple(lvEntry.getServerItem(), lvEntry.isCommitted()), getOp); } } } } // Remove the pending change rows, putting back modified changes for // those entries which were selective undoes. Do this in two loops so // the changes are atomic. final List<LocalPendingChange> selectiveUndoChanges = new ArrayList<LocalPendingChange>(); for (final UndoneChange undoneChange : undoneChanges) { pc.remove(undoneChange.getPendingChange()); // If this was a selective undo, add an entry to the table if (!undoneChange.getUndoneChangeType().equals(undoneChange.getPendingChange().getChangeType())) { final LocalPendingChange newChange = undoneChange.getPendingChange().clone(); newChange.setChangeType( undoneChange.getPendingChange().getChangeType().remove(undoneChange.getUndoneChangeType())); newChange.setTargetServerItem(undoneChange.getRevertToServerItem()); selectiveUndoChanges.add(newChange); } } // Second loop -- pend the selective undo changes. for (final LocalPendingChange pcEntry : selectiveUndoChanges) { pc.pendChange(pcEntry); } // Update the pending changes that were not undone but were affected by // parental renames. // Do this in two loops (remove+capture, modify+apply) so the changes // are atomic. for (final RenamedPendingChange renamedPendingChange : renamedPendingChanges) { final LocalPendingChange pcEntry = pc .getByTargetServerItem(renamedPendingChange.getOldTargetServerItem()); if (null != pcEntry) { pc.remove(pcEntry); renamedPendingChange.setPendingChange(pcEntry); if (!pcEntry.isCommitted()) { final WorkspaceLocalItem lvEntry = lv .getByServerItem(renamedPendingChange.getOldTargetServerItem(), false); if (null != lvEntry) { renamedPendingChange.setLocalVersion(lvEntry); lv.removeByServerItem(lvEntry.getServerItem(), lvEntry.isCommitted(), true); } } } } // Second loop -- apply the data to the tables after modifying it for (final RenamedPendingChange renamedPendingChange : renamedPendingChanges) { final LocalPendingChange pcEntry = renamedPendingChange.getPendingChange(); final WorkspaceLocalItem lvEntry = renamedPendingChange.getLocalVersion(); if (null != pcEntry) { pcEntry.setTargetServerItem(renamedPendingChange.getTargetServerItem()); if (!pcEntry.isCommitted()) { pcEntry.setItemID(0); } pc.pendChange(pcEntry); } if (null != lvEntry) { lvEntry.setServerItem(renamedPendingChange.getTargetServerItem()); lvEntry.setItemID(0); lv.add(lvEntry); } } failures.set(failureList.toArray(new Failure[failureList.size()])); onlineOperationRequired.set(false); return getOps.values().toArray(new GetOperation[getOps.size()]); }