2323import  java .io .RandomAccessFile ;
2424import  java .io .UnsupportedEncodingException ;
2525import  java .util .ArrayList ;
26+ import  java .util .Collection ;
27+ import  java .util .Collections ;
2628import  java .util .HashSet ;
2729import  java .util .List ;
2830import  java .util .Set ;
3537 * library. 
3638 */ 
3739public  class  Parse  {
40+   /** 
41+    * Represents an opaque configuration for the {@code Parse} SDK configuration. 
42+    */ 
43+   public  static  final  class  Configuration  {
44+     /** 
45+      * Allows for simple constructing of a {@code Configuration} object. 
46+      */ 
47+     public  static  final  class  Builder  {
48+       private  Context  context ;
49+       private  String  applicationId ;
50+       private  String  clientKey ;
51+       private  boolean  localDataStoreEnabled ;
52+       private  List <ParseNetworkInterceptor > interceptors ;
53+ 
54+       /** 
55+        * Initialize a bulider with a given context. 
56+        * 
57+        * This context will then be passed through to the rest of the Parse SDK for use during 
58+        * initialization. 
59+        * 
60+        * <p/> 
61+        * You may define {@code com.parse.APPLICATION_ID} and {@code com.parse.CLIENT_KEY} 
62+        * {@code meta-data} in your {@code AndroidManifest.xml}: 
63+        * <pre> 
64+        * <manifest ...> 
65+        * 
66+        * ... 
67+        * 
68+        *   <application ...> 
69+        *     <meta-data 
70+        *       android:name="com.parse.APPLICATION_ID" 
71+        *       android:value="@string/parse_app_id" /> 
72+        *     <meta-data 
73+        *       android:name="com.parse.CLIENT_KEY" 
74+        *       android:value="@string/parse_client_key" /> 
75+        * 
76+        *       ... 
77+        * 
78+        *   </application> 
79+        * </manifest> 
80+        * </pre> 
81+        * <p/> 
82+        * 
83+        * This will cause the values for {@code applicationId} and {@code clientKey} to be set to 
84+        * those defined in your manifest. 
85+        * 
86+        * @param context The active {@link Context} for your application. Cannot be null. 
87+        */ 
88+       public  Builder (Context  context ) {
89+         this .context  = context ;
90+ 
91+         // Yes, our public API states we cannot be null. But for unit tests, it's easier just to 
92+         // support null here. 
93+         if  (context  != null ) {
94+           Context  applicationContext  = context .getApplicationContext ();
95+           Bundle  metaData  = ManifestInfo .getApplicationMetadata (applicationContext );
96+           if  (metaData  != null ) {
97+             applicationId  = metaData .getString (PARSE_APPLICATION_ID );
98+             clientKey  = metaData .getString (PARSE_CLIENT_KEY );
99+           }
100+         }
101+       }
102+ 
103+       /** 
104+        * Set the application id to be used by Parse. 
105+        * 
106+        * This method is only required if you intend to use a different {@code applicationId} than 
107+        * is defined by {@code com.parse.APPLICATION_ID} in your {@code AndroidManifest.xml}. 
108+        * 
109+        * @param applicationId The application id to set. 
110+        * @return The same builder, for easy chaining. 
111+        */ 
112+       public  Builder  applicationId (String  applicationId ) {
113+         this .applicationId  = applicationId ;
114+         return  this ;
115+       }
116+ 
117+       /** 
118+        * Set the client key to be used by Parse. 
119+        * 
120+        * This method is only required if you intend to use a different {@code clientKey} than 
121+        * is defined by {@code com.parse.CLIENT_KEY} in your {@code AndroidManifest.xml}. 
122+        * 
123+        * @param clientKey The client key to set. 
124+        * @return The same builder, for easy chaining. 
125+        */ 
126+       public  Builder  clientKey (String  clientKey ) {
127+         this .clientKey  = clientKey ;
128+         return  this ;
129+       }
130+ 
131+       /** 
132+        * Add a {@link ParseNetworkInterceptor}. 
133+        * 
134+        * @param interceptor The interceptor to add. 
135+        * @return The same builder, for easy chaining. 
136+        */ 
137+       public  Builder  addNetworkInterceptor (ParseNetworkInterceptor  interceptor ) {
138+         if  (interceptors  == null ) {
139+           interceptors  = new  ArrayList <>();
140+         }
141+         interceptors .add (interceptor );
142+         return  this ;
143+       }
144+ 
145+       /** 
146+        * Enable pinning in your application. This must be called before your application can use 
147+        * pinning. 
148+        * @return The same builder, for easy chaining. 
149+        */ 
150+       public  Builder  enableLocalDataStore () {
151+         localDataStoreEnabled  = true ;
152+         return  this ;
153+       }
154+ 
155+       private  Builder  setNetworkInterceptors (Collection <ParseNetworkInterceptor > interceptors ) {
156+         if  (interceptors  != null ) {
157+           this .interceptors .clear ();
158+           this .interceptors .addAll (interceptors );
159+         }
160+         return  this ;
161+       }
162+ 
163+       private  Builder  setLocalDatastoreEnabled (boolean  enabled ) {
164+         localDataStoreEnabled  = enabled ;
165+         return  this ;
166+       }
167+ 
168+       /** 
169+        * Construct this builder into a concrete {@code Configuration} instance. 
170+        * @return A constructed {@code Configuration} object. 
171+        */ 
172+       public  Configuration  build () {
173+         return  new  Configuration (this );
174+       }
175+     }
176+ 
177+     /* package for tests */  final  Context  context ;
178+     /* package for tests */  final  String  applicationId ;
179+     /* package for tests */  final  String  clientKey ;
180+     /* package for tests */  final  boolean  localDataStoreEnabled ;
181+     /* package for tests */  final  List <ParseNetworkInterceptor > interceptors ;
182+ 
183+     private  Configuration (Builder  builder ) {
184+       this .context  = builder .context ;
185+       this .applicationId  = builder .applicationId ;
186+       this .clientKey  = builder .clientKey ;
187+       this .localDataStoreEnabled  = builder .localDataStoreEnabled ;
188+       this .interceptors  = builder .interceptors  != null  ?
189+         Collections .unmodifiableList (new  ArrayList <>(builder .interceptors )) :
190+         null ;
191+     }
192+   }
193+ 
38194  private  static  final  String  PARSE_APPLICATION_ID  = "com.parse.APPLICATION_ID" ;
39195  private  static  final  String  PARSE_CLIENT_KEY  = "com.parse.CLIENT_KEY" ;
40196
@@ -133,32 +289,24 @@ public static void enableLocalDatastore(Context context) {
133289   *          The active {@link Context} for your application. 
134290   */ 
135291  public  static  void  initialize (Context  context ) {
136-     Context  applicationContext  = context .getApplicationContext ();
137-     String  applicationId ;
138-     String  clientKey ;
139-     Bundle  metaData  = ManifestInfo .getApplicationMetadata (applicationContext );
140-     if  (metaData  != null ) {
141-       applicationId  = metaData .getString (PARSE_APPLICATION_ID );
142-       clientKey  = metaData .getString (PARSE_CLIENT_KEY );
143- 
144-       if  (applicationId  == null ) {
145-         throw  new  RuntimeException ("ApplicationId not defined. "  +
146-                 "You must provide ApplicationId in AndroidManifest.xml.\n "  +
147-                 "<meta-data\n "  +
148-                 "    android:name=\" com.parse.APPLICATION_ID\" \n "  +
149-                 "    android:value=\" <Your Application Id>\"  />" );
150-       }
151-       if  (clientKey  == null ) {
152-         throw  new  RuntimeException ("ClientKey not defined. "  +
153-                 "You must provide ClientKey in AndroidManifest.xml.\n "  +
154-                 "<meta-data\n "  +
155-                 "    android:name=\" com.parse.CLIENT_KEY\" \n "  +
156-                 "    android:value=\" <Your Client Key>\"  />" );
157-       }
158-     } else  {
159-       throw  new  RuntimeException ("Can't get Application Metadata" );
292+     Configuration .Builder  builder  = new  Configuration .Builder (context );
293+     if  (builder .applicationId  == null ) {
294+       throw  new  RuntimeException ("ApplicationId not defined. "  +
295+         "You must provide ApplicationId in AndroidManifest.xml.\n "  +
296+         "<meta-data\n "  +
297+         "    android:name=\" com.parse.APPLICATION_ID\" \n "  +
298+         "    android:value=\" <Your Application Id>\"  />" );
299+     } if  (builder .clientKey  == null ) {
300+       throw  new  RuntimeException ("ClientKey not defined. "  +
301+         "You must provide ClientKey in AndroidManifest.xml.\n "  +
302+         "<meta-data\n "  +
303+         "    android:name=\" com.parse.CLIENT_KEY\" \n "  +
304+         "    android:value=\" <Your Client Key>\"  />" );
160305    }
161-     initialize (context , applicationId , clientKey );
306+     initialize (builder .setNetworkInterceptors (interceptors )
307+         .setLocalDatastoreEnabled (isLocalDatastoreEnabled )
308+         .build ()
309+     );
162310  }
163311
164312  /** 
@@ -188,22 +336,36 @@ public static void initialize(Context context) {
188336   *          The client key provided in the Parse dashboard. 
189337   */ 
190338  public  static  void  initialize (Context  context , String  applicationId , String  clientKey ) {
191-     ParsePlugins .Android .initialize (context , applicationId , clientKey );
192-     Context  applicationContext  = context .getApplicationContext ();
339+     initialize (new  Configuration .Builder (context )
340+         .applicationId (applicationId )
341+         .clientKey (clientKey )
342+         .setNetworkInterceptors (interceptors )
343+         .setLocalDatastoreEnabled (isLocalDatastoreEnabled )
344+         .build ()
345+     );
346+   }
347+ 
348+   public  static  void  initialize (Configuration  configuration ) {
349+     // NOTE (richardross): We will need this here, as ParsePlugins uses the return value of 
350+     // isLocalDataStoreEnabled() to perform additional behavior. 
351+     isLocalDatastoreEnabled  = configuration .localDataStoreEnabled ;
352+ 
353+     ParsePlugins .Android .initialize (configuration .context , configuration .applicationId , configuration .clientKey );
354+     Context  applicationContext  = configuration .context .getApplicationContext ();
193355
194356    ParseHttpClient .setKeepAlive (true );
195357    ParseHttpClient .setMaxConnections (20 );
196358    // If we have interceptors in list, we have to initialize all http clients and add interceptors 
197-     if  (interceptors  != null ) {
198-       initializeParseHttpClientsWithParseNetworkInterceptors ();
359+     if  (configuration . interceptors  != null ) {
360+       initializeParseHttpClientsWithParseNetworkInterceptors (configuration . interceptors );
199361    }
200362
201363    ParseObject .registerParseSubclasses ();
202364
203-     if  (isLocalDatastoreEnabled () ) {
204-       offlineStore  = new  OfflineStore (context );
365+     if  (configuration . localDataStoreEnabled ) {
366+       offlineStore  = new  OfflineStore (configuration . context );
205367    } else  {
206-       ParseKeyValueCache .initialize (context );
368+       ParseKeyValueCache .initialize (configuration . context );
207369    }
208370
209371    // Make sure the data on disk for Parse is for the current 
@@ -583,7 +745,7 @@ private Parse() {
583745  private  static  List <ParseNetworkInterceptor > interceptors ;
584746
585747  // Initialize all necessary http clients and add interceptors to these http clients 
586-   private  static  void  initializeParseHttpClientsWithParseNetworkInterceptors () {
748+   private  static  void  initializeParseHttpClientsWithParseNetworkInterceptors (List < ParseNetworkInterceptor >  interceptors ) {
587749    // This means developers have not called addInterceptor method so we should do nothing. 
588750    if  (interceptors  == null ) {
589751      return ;
@@ -605,9 +767,6 @@ private static void initializeParseHttpClientsWithParseNetworkInterceptors() {
605767        parseHttpClient .addExternalInterceptor (interceptor );
606768      }
607769    }
608- 
609-     // Remove interceptors reference since we do not need it anymore 
610-     interceptors  = null ;
611770  }
612771
613772
0 commit comments