diff --git a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java index ee370bea5a58..5c5dcd496d61 100644 --- a/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java +++ b/google-cloud-clients/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQuery.java @@ -753,13 +753,19 @@ public int hashCode() { * Updates dataset information. * *

Example of updating a dataset by changing its description. - *

 {@code
-   * String datasetName = "my_dataset_name";
-   * String newDescription = "some_new_description";
-   * Dataset oldDataset = bigquery.getDataset(datasetName);
-   * DatasetInfo datasetInfo = oldDataset.toBuilder().setDescription(newDescription).build();
-   * Dataset newDataset = bigquery.update(datasetInfo);
-   * }
+ * + *
{@code
+   *    // String datasetName = "my_dataset_name";
+   *    // String tableName = "my_table_name";
+   *    // String newDescription = "new_description";
+   *
+   *    Table beforeTable = bigquery.getTable(datasetName, tableName);
+   *    TableInfo tableInfo = beforeTable.toBuilder()
+   *        .setDescription(newDescription)
+   *        .build();
+   *    Table afterTable = bigquery.update(tableInfo);
+   *     }
+ * * * @throws BigQueryException upon failure */ @@ -785,7 +791,7 @@ public int hashCode() { * String datasetName = "my_dataset_name"; * String tableName = "my_table_name"; * Table beforeTable = bigquery.getTable(datasetName, tableName); - * + * * // Set table to expire 5 days from now. * long expirationMillis = DateTime.now().plusDays(5).getMillis(); * TableInfo tableInfo = beforeTable.toBuilder() @@ -1104,7 +1110,7 @@ TableResult listTableData( * // BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService(); * String query = "SELECT corpus FROM `bigquery-public-data.samples.shakespeare` GROUP BY corpus;"; * QueryJobConfiguration queryConfig = QueryJobConfiguration.newBuilder(query).build(); - * + * * // Print the results. * for (FieldValueList row : bigquery.query(queryConfig).iterateAll()) { * for (FieldValue val : row) { diff --git a/google-cloud-clients/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/v1/MessageReceiver.java b/google-cloud-clients/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/v1/MessageReceiver.java index c247260d3831..d1428a6d5cc2 100644 --- a/google-cloud-clients/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/v1/MessageReceiver.java +++ b/google-cloud-clients/google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/v1/MessageReceiver.java @@ -22,27 +22,31 @@ public interface MessageReceiver { /** * Called when a message is received by the subscriber. The implementation must arrange for {@link - * AckReplyConsumer#ack()} or {@link - * AckReplyConsumer#nack()} to be called after processing the {@code message}. + * AckReplyConsumer#ack()} or {@link AckReplyConsumer#nack()} to be called after processing the + * {@code message}. + * * - *

This {@code MessageReceiver} passes all messages to a {@code BlockingQueue}. - * This method can be called concurrently from multiple threads, - * so it is important that the queue be thread-safe. + *

{@code
+   * // This {@code MessageReceiver} passes all messages to a {@link BlockingQueue}. This method can
+   * // be called concurrently from multiple threads, so it is important that the queue be
+   * // thread-safe.
+   * //
+   * // This example is for illustration. Implementations may directly process messages instead of
+   * // sending them to queues.
+   * MessageReceiver receiver =
+   *     new MessageReceiver() {
+   *       public void receiveMessage(final PubsubMessage message, final AckReplyConsumer consumer) {
+   *         if (blockingQueue.offer(message)) {
+   *           consumer.ack();
+   *         } else {
+   *           consumer.nack();
+   *         }
+   *       }
+   *     };
    *
-   * This example is for illustration. Implementations may directly process messages
-   * instead of sending them to queues.
-   * 
 {@code
-   * MessageReceiver receiver = new MessageReceiver() {
-   *   public void receiveMessage(final PubsubMessage message, final AckReplyConsumer consumer) {
-   *     if (blockingQueue.offer(message)) {
-   *       consumer.ack();
-   *     } else {
-   *       consumer.nack();
-   *     }
-   *   }
-   * };
    * }
* + * */ void receiveMessage(final PubsubMessage message, final AckReplyConsumer consumer); } diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/bigquery/snippets/BigQuerySnippets.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/bigquery/snippets/BigQuerySnippets.java index b1edd909c041..5724d1c93c37 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/bigquery/snippets/BigQuerySnippets.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/bigquery/snippets/BigQuerySnippets.java @@ -121,12 +121,12 @@ public Dataset updateDataset(String datasetName, String newDescription) { /** * Example of updating a table by changing its description. */ - // [TARGET update(TableInfo, TableOption...)] - // [VARIABLE "my_dataset_name"] - // [VARIABLE "my_table_name"] - // [VARIABLE "new_description"] public Table updateTableDescription(String datasetName, String tableName, String newDescription) { // [START bigquery_update_table_description] + // String datasetName = "my_dataset_name"; + // String tableName = "my_table_name"; + // String newDescription = "new_description"; + Table beforeTable = bigquery.getTable(datasetName, tableName); TableInfo tableInfo = beforeTable.toBuilder() .setDescription(newDescription) diff --git a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/MessageReceiverSnippets.java b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/MessageReceiverSnippets.java index 48aa27bdbf57..f082afa40f0a 100644 --- a/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/MessageReceiverSnippets.java +++ b/google-cloud-examples/src/main/java/com/google/cloud/examples/pubsub/snippets/MessageReceiverSnippets.java @@ -36,25 +36,25 @@ public MessageReceiverSnippets(BlockingQueue blockingQueue) { this.blockingQueue = blockingQueue; } - /** - * This {@code MessageReceiver} passes all messages to a {@link BlockingQueue}. - * This method can be called concurrently from multiple threads, - * so it is important that the queue be thread-safe. - * - * This example is for illustration. Implementations may directly process messages - * instead of sending them to queues. - */ - // [TARGET receiveMessage(PubsubMessage, AckReplyConsumer)] public MessageReceiver messageReceiver() { - MessageReceiver receiver = new MessageReceiver() { - public void receiveMessage(final PubsubMessage message, final AckReplyConsumer consumer) { - if (blockingQueue.offer(message)) { - consumer.ack(); - } else { - consumer.nack(); - } - } - }; + // SNIPPET receiveMessage + // This {@code MessageReceiver} passes all messages to a {@link BlockingQueue}. This method can + // be called concurrently from multiple threads, so it is important that the queue be + // thread-safe. + // + // This example is for illustration. Implementations may directly process messages instead of + // sending them to queues. + MessageReceiver receiver = + new MessageReceiver() { + public void receiveMessage(final PubsubMessage message, final AckReplyConsumer consumer) { + if (blockingQueue.offer(message)) { + consumer.ack(); + } else { + consumer.nack(); + } + } + }; + // SNIPPET receiveMessage return receiver; } } diff --git a/utilities/snippets.go b/utilities/snippets.go new file mode 100644 index 000000000000..5a9c66204c37 --- /dev/null +++ b/utilities/snippets.go @@ -0,0 +1,230 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bytes" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "runtime/pprof" + "strings" +) + +func init() { + log.SetFlags(0) + log.SetPrefix("snippet: ") +} + +func main() { + cpuprof := flag.String("cpuprofile", "", "write CPU profile to this file") + flag.Parse() + + if cp := *cpuprof; cp != "" { + f, err := os.Create(cp) + if err != nil { + log.Fatal(err) + } + defer f.Close() + + pprof.StartCPUProfile(f) + defer pprof.StopCPUProfile() + } + + files := map[string]string{} + walkFn := func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.Mode().IsRegular() || filepath.Ext(path) != ".java" { + return nil + } + b, err := ioutil.ReadFile(path) + if err != nil { + return err + } + files[path] = string(b) + return nil + } + for _, dir := range flag.Args() { + if err := filepath.Walk(dir, walkFn); err != nil { + log.Fatal(err) + } + } + + snip := map[string]string{} + for file, txt := range files { + if err := getSnip(file, txt, snip); err != nil { + log.Fatal(err) + } + if err := getCloud(file, txt, snip); err != nil { + log.Fatal(err) + } + } + + rd := rewriteData{ + rewrite: map[string]string{}, + used: map[string]bool{}, + } + for file, txt := range files { + if err := writeSnip(file, txt, snip, rd); err != nil { + log.Fatal(err) + } + } + + for file, txt := range rd.rewrite { + if err := ioutil.WriteFile(file, []byte(txt), 0644); err != nil { + log.Fatal(err) + } + } + + for key := range snip { + if !rd.used[key] { + log.Printf("unused snippet: %q", key) + } + } +} + +func getCloud(file, txt string, snip map[string]string) error { + const cloudPrefix = "// [START " + const cloudSuffix = "// [END %s]" + + ftxt := txt + for { + if p := strings.Index(txt, cloudPrefix); p >= 0 { + txt = txt[p:] + } else { + return nil + } + + var tag string + if p := strings.Index(txt, "]\n"); p >= 0 { + // "// [START foo]" -> "foo" + tag = txt[10:p] + txt = txt[p+1:] + } else { + tag = txt + txt = "" + } + + endTag := fmt.Sprintf(cloudSuffix, tag) + if p := strings.Index(txt, endTag); p >= 0 { + key := fmt.Sprintf("", tag) + snipTxt := strings.Trim(txt[:p], "\n\r") + if _, exist := snip[key]; exist { + snip[key] = strings.Join([]string{snip[key], snipTxt}, "") + } + + snip[key] = snipTxt + txt = txt[p+len(endTag):] + } else { + return fmt.Errorf("[START %s]:%d snippet %q not closed", file, lineNum(ftxt, txt), tag) + } + } +} + +func getSnip(file, txt string, snip map[string]string) error { + const snipPrefix = "// SNIPPET " + + ftxt := txt + for { + if p := strings.Index(txt, snipPrefix); p >= 0 { + txt = txt[p:] + } else { + return nil + } + + var key string + if p := strings.IndexByte(txt, '\n'); p >= 0 { + key = txt[:p] + txt = txt[p:] + } else { + key = txt + txt = "" + } + + if p := strings.Index(txt, key); p >= 0 { + // "// SNIPPET foo" -> "" + key = fmt.Sprintf("", strings.TrimSpace(key[3:])) + + if _, exist := snip[key]; exist { + return fmt.Errorf("%s:%d snippet %q has already been defined", file, lineNum(ftxt, txt), key) + } + + snip[key] = strings.Trim(txt[:p], "\n\r") + txt = txt[p+len(snipPrefix):] + } else { + return fmt.Errorf("%s:%d snippet %q not closed", file, lineNum(ftxt, txt), key) + } + } +} + +type rewriteData struct { + rewrite map[string]string + used map[string]bool +} + +func writeSnip(file, txt string, snip map[string]string, rd rewriteData) error { + const snipPrefix = ""); p >= 0 { + key = txt[:p+3] + txt = txt[p+3:] + } + + rep, ok := snip[key] + if ok { + rd.used[key] = true + } else { + return fmt.Errorf("%s:%d snippet target %q undefined", file, lineNum(ftxt, txt), key) + } + + if p := strings.Index(txt, key); p >= 0 { + buf.WriteString(key) + buf.WriteString("\n *
{@code\n   *")
+			buf.WriteString(strings.Replace(rep, "\n", "\n   *", -1))
+			buf.WriteString(" }
\n * ") + buf.WriteString(key) + txt = txt[p+len(key):] + } else { + return fmt.Errorf("%s:%d snippet target %q not closed", file, lineNum(ftxt, txt), key) + } + } +} + +// Give strings s and suf where suf is a suffix of s, lineNum reports +// the line number on which suf starts. +func lineNum(s, suf string) int { + pre := s[:len(s)-len(suf)] + return strings.Count(pre, "\n") + 1 +} diff --git a/utilities/snippets_test.go b/utilities/snippets_test.go new file mode 100644 index 000000000000..0938a2bd4638 --- /dev/null +++ b/utilities/snippets_test.go @@ -0,0 +1,167 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package main + +import ( + "reflect" + "testing" +) + +var sniptests = []struct { + txt string + out map[string]string +}{ + { + `package com.google.cloud.examples.pubsub.snippets; + +import com.google.cloud.pubsub.v1.AckReplyConsumer; +import com.google.cloud.pubsub.v1.MessageReceiver; +import com.google.pubsub.v1.PubsubMessage; +import java.util.concurrent.BlockingQueue; + +/** This class contains snippets for the {@link MessageReceiver} interface. */ + +public class MessageReceiverSnippets { + private final BlockingQueue blockingQueue; + + public MessageReceiverSnippets(BlockingQueue blockingQueue) { + this.blockingQueue = blockingQueue; + } + + public MessageReceiver messageReceiver() { + // SNIPPET receiveMessage + MessageReceiver receiver = + new MessageReceiver() { + public void receiveMessage(final PubsubMessage message, final AckReplyConsumer consumer) { + if (blockingQueue.offer(message)) { + consumer.ack(); + } else { + consumer.nack(); + } + } + }; + // SNIPPET receiveMessage + return receiver; + } + + // SNIPPET secondSnippet + // some example code. + // SNIPPET secondSnippet +} +`, + map[string]string{ + "": ` MessageReceiver receiver = + new MessageReceiver() { + public void receiveMessage(final PubsubMessage message, final AckReplyConsumer consumer) { + if (blockingQueue.offer(message)) { + consumer.ack(); + } else { + consumer.nack(); + } + } + }; + `, + "": "\t// some example code.\n\t", + }, + }, +} + +func TestGetSnip(t *testing.T) { + for _, tt := range sniptests { + t.Run(tt.txt, func(t *testing.T) { + + got := map[string]string{} + if err := getSnip("testfile.java", tt.txt, got); err != nil { + t.Errorf("error getting snips: %s", err) + } + if !reflect.DeepEqual(tt.out, got) { + t.Errorf("expected %v, got %v", tt.out, got) + } + }) + } +} + +var cloudtests = []struct { + txt string + out map[string]string +}{ + { + `package com.google.cloud.examples.pubsub.snippets; + +import com.google.cloud.pubsub.v1.AckReplyConsumer; +import com.google.cloud.pubsub.v1.MessageReceiver; +import com.google.pubsub.v1.PubsubMessage; +import java.util.concurrent.BlockingQueue; + +/** This class contains snippets for the {@link MessageReceiver} interface. */ + +public class MessageReceiverSnippets { + private final BlockingQueue blockingQueue; + + public MessageReceiverSnippets(BlockingQueue blockingQueue) { + this.blockingQueue = blockingQueue; + } + + public MessageReceiver messageReceiver() { + // [START pubsub_receive_message] + MessageReceiver receiver = + new MessageReceiver() { + public void receiveMessage(final PubsubMessage message, final AckReplyConsumer consumer) { + if (blockingQueue.offer(message)) { + consumer.ack(); + } else { + consumer.nack(); + } + } + }; + // [END pubsub_receive_message] + return receiver; + } + + // [START pubsub_second_snippet] + // some example code. + // [END pubsub_second_snippet] +} +`, + map[string]string{ + "": ` MessageReceiver receiver = + new MessageReceiver() { + public void receiveMessage(final PubsubMessage message, final AckReplyConsumer consumer) { + if (blockingQueue.offer(message)) { + consumer.ack(); + } else { + consumer.nack(); + } + } + }; + `, + "": "\t// some example code.\n\t", + }, + }, +} + +func TestGetCloud(t *testing.T) { + for _, tt := range cloudtests { + t.Run(tt.txt, func(t *testing.T) { + + got := map[string]string{} + if err := getCloud("testfile.java", tt.txt, got); err != nil { + t.Errorf("error getting cloud snips: %s", err) + } + if !reflect.DeepEqual(tt.out, got) { + t.Errorf("expected %v, got %v", tt.out, got) + } + }) + } +}